Skip to content

Commit

Permalink
handle interprogram branches, indent options
Browse files Browse the repository at this point in the history
  • Loading branch information
dfgordon committed Aug 11, 2024
1 parent 4cd70eb commit 1844656
Show file tree
Hide file tree
Showing 12 changed files with 185 additions and 57 deletions.
47 changes: 30 additions & 17 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,34 +1,47 @@
# 3.0.0
# Changelog

(in progress)
All notable changes to this project will be documented in this file.

## Major Features
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [3.0.0] - 2024-08-11

### New Features

* Language servers for Applesoft, Integer BASIC, and Merlin
- these can be used to support any editor that implements the LSP
* `a2kit verify` performs a much deeper language analysis
* Disassembler for 6502, 65c02, and 65816
* Limited assembler for Merlin 8, 16, 16+, 32
* new CLI subcommands `mget` and `mput` for efficient multi-file handling
* new CLI subcommands `pack` and `unpack` for direct manipulation of file images

## Other Updates

* You can glob (search) a disk image using `a2kit glob`
* new CLI subcommands
- `mget` and `mput` for efficient multi-file handling
- `pack` and `unpack` for direct manipulation of file images
- `glob` allows you to glob (search) any solvable disk image
* new CLI subcommand options
- `get -t auto` will automatically select an unpacking strategy
- `catalog --generic` will produce the same columns no matter the FS
- some subcommands have `--indent` option to control JSON formatting
* Applesoft optionally accepts extended CALL syntax
* Integer optionally accepts immediate mode commands
* Better renumbering
* Renumbering optionally allows for movement of lines

### Fixes

* Eliminate some possible panics
* Better handling of 16 bit Merlin syntax
* Better ProDOS Y2K handling
* Better handling of CP/M files with no extension
* `catalog` has `--generic` option for easy parsing with any file system
* `get` has `-t auto` to automatically select a decoding strategy
* More control over JSON formatting
* Eliminate some possible panics

## Breaking Changes
### New Behaviors

Most of the JSON outputs will now default to a minified format. This is optimal when `a2kit` is being called as a subprocess or library. Users of the raw CLI can recover pretty formatting using the `--indent` option.

### Breaking Changes

CLI scripts written for v2 should still work with v3, *unless* a user's JSON parser is checking the *length* of certain arrays, or checking for unknown keys.

Breaking changes are all at the level of the library. CLI scripts written for v2 should still work with v3, *unless* a user's JSON parser is checking the *length* of certain arrays.
Users of the `a2kit` library crate will have to consider the following before upgrading to v3:

* Extracting files from a disk image works differently
- The `FileImage` object handles packing or unpacking various data types, while `DiskFS` works only with `FileImage`.
Expand All @@ -40,7 +53,7 @@ Breaking changes are all at the level of the library. CLI scripts written for v
* FileImage 2.1.0 is the default, this adds two root level keys
- `full_path` key which is mainly useful for `mput`
- `accessed` key which can be used by FAT file systems
* Functions calls that will need to be reviewed
* Function calls that will need to be revised
- `a2kit_macro::DiskStruct::from_bytes`
- `a2kit_macro::DiskStruct::update_from_bytes`
- `img::DiskImage::from_bytes`
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ tempfile = "3.6.0"
json = "0.12"
serde = "1.0.116"
serde_json = "1.0.116"
chrono = "0.4.20"
chrono = "0.4.35"
regex = "1.10"
predicates = "2.1.0"
assert_cmd = "2.0.2"
Expand Down
3 changes: 3 additions & 0 deletions completions/_a2kit
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ _arguments "${_arguments_options[@]}" : \
'--type+[type of the item]:TYPE:(any auto bin txt raw rec atok itok mtok block sec track raw_track meta)' \
'-d+[path to disk image itself]:PATH:_files' \
'--dimg+[path to disk image itself]:PATH:_files' \
'--indent+[JSON indentation, omit to minify]:SPACES: ' \
'-l+[length of record in DOS 3.3 random access text file]:LENGTH: ' \
'--len+[length of record in DOS 3.3 random access text file]:LENGTH: ' \
'--trunc[truncate raw at EOF if possible]' \
Expand All @@ -61,6 +62,7 @@ _arguments "${_arguments_options[@]}" : \
_arguments "${_arguments_options[@]}" : \
'-d+[path to disk image itself]:PATH:_files' \
'--dimg+[path to disk image itself]:PATH:_files' \
'--indent+[JSON indentation, omit to minify]:SPACES: ' \
'-h[Print help]' \
'--help[Print help]' \
&& ret=0
Expand All @@ -87,6 +89,7 @@ _arguments "${_arguments_options[@]}" : \
'--block+[size of block in bytes if needed]:BYTES: ' \
'-o+[operating system format]:OS:(cpm2 cpm3 dos32 dos33 prodos pascal fat)' \
'--os+[operating system format]:OS:(cpm2 cpm3 dos32 dos33 prodos pascal fat)' \
'--indent+[JSON indentation, omit to minify]:SPACES: ' \
'-h[Print help]' \
'--help[Print help]' \
&& ret=0
Expand Down
3 changes: 3 additions & 0 deletions completions/_a2kit.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ Register-ArgumentCompleter -Native -CommandName 'a2kit' -ScriptBlock {
[CompletionResult]::new('--type', 'type', [CompletionResultType]::ParameterName, 'type of the item')
[CompletionResult]::new('-d', 'd', [CompletionResultType]::ParameterName, 'path to disk image itself')
[CompletionResult]::new('--dimg', 'dimg', [CompletionResultType]::ParameterName, 'path to disk image itself')
[CompletionResult]::new('--indent', 'indent', [CompletionResultType]::ParameterName, 'JSON indentation, omit to minify')
[CompletionResult]::new('-l', 'l', [CompletionResultType]::ParameterName, 'length of record in DOS 3.3 random access text file')
[CompletionResult]::new('--len', 'len', [CompletionResultType]::ParameterName, 'length of record in DOS 3.3 random access text file')
[CompletionResult]::new('--trunc', 'trunc', [CompletionResultType]::ParameterName, 'truncate raw at EOF if possible')
Expand All @@ -92,6 +93,7 @@ Register-ArgumentCompleter -Native -CommandName 'a2kit' -ScriptBlock {
'a2kit;mget' {
[CompletionResult]::new('-d', 'd', [CompletionResultType]::ParameterName, 'path to disk image itself')
[CompletionResult]::new('--dimg', 'dimg', [CompletionResultType]::ParameterName, 'path to disk image itself')
[CompletionResult]::new('--indent', 'indent', [CompletionResultType]::ParameterName, 'JSON indentation, omit to minify')
[CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
[CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
break
Expand All @@ -116,6 +118,7 @@ Register-ArgumentCompleter -Native -CommandName 'a2kit' -ScriptBlock {
[CompletionResult]::new('--block', 'block', [CompletionResultType]::ParameterName, 'size of block in bytes if needed')
[CompletionResult]::new('-o', 'o', [CompletionResultType]::ParameterName, 'operating system format')
[CompletionResult]::new('--os', 'os', [CompletionResultType]::ParameterName, 'operating system format')
[CompletionResult]::new('--indent', 'indent', [CompletionResultType]::ParameterName, 'JSON indentation, omit to minify')
[CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help')
[CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help')
break
Expand Down
18 changes: 15 additions & 3 deletions completions/a2kit.bash
Original file line number Diff line number Diff line change
Expand Up @@ -742,7 +742,7 @@ _a2kit() {
return 0
;;
a2kit__get)
opts="-f -t -d -l -h --file --type --dimg --len --trunc --help"
opts="-f -t -d -l -h --file --type --dimg --indent --len --trunc --help"
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
Expand Down Expand Up @@ -816,6 +816,10 @@ _a2kit() {
fi
return 0
;;
--indent)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--len)
COMPREPLY=($(compgen -f "${cur}"))
return 0
Expand Down Expand Up @@ -1346,7 +1350,7 @@ _a2kit() {
return 0
;;
a2kit__mget)
opts="-d -h --dimg --help"
opts="-d -h --dimg --indent --help"
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
Expand Down Expand Up @@ -1382,6 +1386,10 @@ _a2kit() {
fi
return 0
;;
--indent)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
*)
COMPREPLY=()
;;
Expand Down Expand Up @@ -1630,7 +1638,7 @@ _a2kit() {
return 0
;;
a2kit__pack)
opts="-f -t -a -b -o -h --file --type --addr --block --os --help"
opts="-f -t -a -b -o -h --file --type --addr --block --os --indent --help"
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
Expand Down Expand Up @@ -1698,6 +1706,10 @@ _a2kit() {
COMPREPLY=($(compgen -W "cpm2 cpm3 dos32 dos33 prodos pascal fat" -- "${cur}"))
return 0
;;
--indent)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
*)
COMPREPLY=()
;;
Expand Down
3 changes: 3 additions & 0 deletions completions/a2kit.elv
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ set edit:completion:arg-completer[a2kit] = {|@words|
cand --type 'type of the item'
cand -d 'path to disk image itself'
cand --dimg 'path to disk image itself'
cand --indent 'JSON indentation, omit to minify'
cand -l 'length of record in DOS 3.3 random access text file'
cand --len 'length of record in DOS 3.3 random access text file'
cand --trunc 'truncate raw at EOF if possible'
Expand All @@ -86,6 +87,7 @@ set edit:completion:arg-completer[a2kit] = {|@words|
&'a2kit;mget'= {
cand -d 'path to disk image itself'
cand --dimg 'path to disk image itself'
cand --indent 'JSON indentation, omit to minify'
cand -h 'Print help'
cand --help 'Print help'
}
Expand All @@ -108,6 +110,7 @@ set edit:completion:arg-completer[a2kit] = {|@words|
cand --block 'size of block in bytes if needed'
cand -o 'operating system format'
cand --os 'operating system format'
cand --indent 'JSON indentation, omit to minify'
cand -h 'Print help'
cand --help 'Print help'
}
Expand Down
3 changes: 3 additions & 0 deletions completions/a2kit.fish
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ complete -c a2kit -n "__fish_a2kit_needs_command" -f -a "help" -d 'Print this me
complete -c a2kit -n "__fish_a2kit_using_subcommand get" -s f -l file -d 'path, key, or address, maybe inside disk image' -r -F
complete -c a2kit -n "__fish_a2kit_using_subcommand get" -s t -l type -d 'type of the item' -r -f -a "{any\t'',auto\t'',bin\t'',txt\t'',raw\t'',rec\t'',atok\t'',itok\t'',mtok\t'',block\t'',sec\t'',track\t'',raw_track\t'',meta\t''}"
complete -c a2kit -n "__fish_a2kit_using_subcommand get" -s d -l dimg -d 'path to disk image itself' -r -F
complete -c a2kit -n "__fish_a2kit_using_subcommand get" -l indent -d 'JSON indentation, omit to minify' -r
complete -c a2kit -n "__fish_a2kit_using_subcommand get" -s l -l len -d 'length of record in DOS 3.3 random access text file' -r
complete -c a2kit -n "__fish_a2kit_using_subcommand get" -l trunc -d 'truncate raw at EOF if possible'
complete -c a2kit -n "__fish_a2kit_using_subcommand get" -s h -l help -d 'Print help'
Expand All @@ -73,6 +74,7 @@ complete -c a2kit -n "__fish_a2kit_using_subcommand put" -s d -l dimg -d 'path t
complete -c a2kit -n "__fish_a2kit_using_subcommand put" -s a -l addr -d 'load-address if applicable' -r
complete -c a2kit -n "__fish_a2kit_using_subcommand put" -s h -l help -d 'Print help'
complete -c a2kit -n "__fish_a2kit_using_subcommand mget" -s d -l dimg -d 'path to disk image itself' -r -F
complete -c a2kit -n "__fish_a2kit_using_subcommand mget" -l indent -d 'JSON indentation, omit to minify' -r
complete -c a2kit -n "__fish_a2kit_using_subcommand mget" -s h -l help -d 'Print help'
complete -c a2kit -n "__fish_a2kit_using_subcommand mput" -s d -l dimg -d 'path to disk image itself' -r -F
complete -c a2kit -n "__fish_a2kit_using_subcommand mput" -s f -l file -d 'override target paths' -r -F
Expand All @@ -82,6 +84,7 @@ complete -c a2kit -n "__fish_a2kit_using_subcommand pack" -s t -l type -d 'type
complete -c a2kit -n "__fish_a2kit_using_subcommand pack" -s a -l addr -d 'load-address if applicable' -r
complete -c a2kit -n "__fish_a2kit_using_subcommand pack" -s b -l block -d 'size of block in bytes if needed' -r
complete -c a2kit -n "__fish_a2kit_using_subcommand pack" -s o -l os -d 'operating system format' -r -f -a "{cpm2\t'',cpm3\t'',dos32\t'',dos33\t'',prodos\t'',pascal\t'',fat\t''}"
complete -c a2kit -n "__fish_a2kit_using_subcommand pack" -l indent -d 'JSON indentation, omit to minify' -r
complete -c a2kit -n "__fish_a2kit_using_subcommand pack" -s h -l help -d 'Print help'
complete -c a2kit -n "__fish_a2kit_using_subcommand unpack" -s t -l type -d 'type of the item' -r -f -a "{auto\t'',bin\t'',txt\t'',raw\t'',rec\t'',atok\t'',itok\t'',mtok\t''}"
complete -c a2kit -n "__fish_a2kit_using_subcommand unpack" -s l -l len -d 'length of record in DOS 3.3 random access text file' -r
Expand Down
5 changes: 4 additions & 1 deletion src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ Detokenize from image: `a2kit get -f prog -t atok -d myimg.dsk | a2kit detokeniz
.value_name("TYPE").required(false).value_parser(get_put_types)
)
.arg(dimg_arg_opt.clone())
.arg(indent_arg.clone())
.arg(Arg::new("len").long("len").short('l').help("length of record in DOS 3.3 random access text file")
.value_name("LENGTH").required(false)
)
Expand All @@ -131,6 +132,7 @@ Detokenize from image: `a2kit get -f prog -t atok -d myimg.dsk | a2kit detokeniz
main_cmd = main_cmd.subcommand(
Command::new("mget")
.arg(dimg_arg_req.clone())
.arg(indent_arg.clone())
.about("read list of paths from stdin, get files from disk image, write file images to stdout")
.after_help("this can take `a2kit glob` as a piped input")
);
Expand Down Expand Up @@ -161,6 +163,7 @@ Detokenize from image: `a2kit get -f prog -t atok -d myimg.dsk | a2kit detokeniz
.required(true)
.value_parser(os_names)
)
.arg(indent_arg.clone())
.about("pack data into a file image")
);
main_cmd = main_cmd.subcommand(
Expand Down Expand Up @@ -422,7 +425,7 @@ Detokenize from image: `a2kit get -f prog -t atok -d myimg.dsk | a2kit detokeniz
)
.arg(indent_arg.clone())
.about("write JSON list of matching paths to stdout")
.after_help(IN_HELP)
.after_help("the pattern may need to be quoted depending on shell\n\n".to_string() + IN_HELP)
);
return main_cmd;
}
16 changes: 10 additions & 6 deletions src/commands/get.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ fn output_get(result: UnpackedData, load_addr: usize) -> STDRESULT {
Ok(())
}

fn unpack_primitive(fimg: &FileImage,typ: ItemType,rec_len: Option<usize>,trunc: bool) -> Result<UnpackedData,DYNERR> {
fn unpack_primitive(fimg: &FileImage,typ: ItemType,rec_len: Option<usize>,trunc: bool,indent: Option<u16>) -> Result<UnpackedData,DYNERR> {
match typ {
ItemType::Automatic => fimg.unpack(),
ItemType::FileImage => Ok(UnpackedData::Text(fimg.to_json(Some(2)))),
ItemType::Records => Ok(UnpackedData::Text(fimg.unpack_rec_str(rec_len,Some(2))?)),
ItemType::FileImage => Ok(UnpackedData::Text(fimg.to_json(indent))),
ItemType::Records => Ok(UnpackedData::Text(fimg.unpack_rec_str(rec_len,indent)?)),
ItemType::ApplesoftTokens => Ok(UnpackedData::Binary(fimg.unpack_tok()?)),
ItemType::IntegerTokens => Ok(UnpackedData::Binary(fimg.unpack_tok()?)),
ItemType::MerlinTokens => Ok(UnpackedData::Binary(fimg.unpack_raw(true)?)),
Expand Down Expand Up @@ -58,7 +58,7 @@ pub fn unpack(cmd: &clap::ArgMatches) -> STDRESULT {
};
let json_str = String::from_utf8(dat)?;
let fimg = FileImage::from_json(&json_str)?;
let result = unpack_primitive(&fimg, typ, rec_len, trunc)?;
let result = unpack_primitive(&fimg, typ, rec_len, trunc, cmd.get_one::<u16>("indent").copied())?;
output_get(result, fimg.get_load_address() as usize)
}

Expand Down Expand Up @@ -103,7 +103,7 @@ pub fn get(cmd: &clap::ArgMatches) -> STDRESULT {
return output_get(UnpackedData::Binary(cum),0);
}
let fimg = disk.get(&src_path)?;
let result = unpack_primitive(&fimg, typ, rec_len, trunc)?;
let result = unpack_primitive(&fimg, typ, rec_len, trunc, cmd.get_one::<u16>("indent").copied())?;
return output_get(result,fimg.get_load_address() as usize);
},

Expand Down Expand Up @@ -161,6 +161,10 @@ pub fn mget(cmd: &clap::ArgMatches) -> STDRESULT {
let fimg = disk.get(path.as_str().unwrap())?;
ans.push(json::parse(&fimg.to_json(None))?)?;
}
println!("{}",ans.to_string());
if let Some(spaces) = cmd.get_one::<u16>("indent") {
println!("{}",json::stringify_pretty(ans,*spaces));
} else {
println!("{}",json::stringify(ans))
}
return Ok(());
}
2 changes: 1 addition & 1 deletion src/commands/put.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ pub fn pack(cmd: &clap::ArgMatches) -> STDRESULT {
_ => return Err(Box::new(CommandError::UnknownItemType))
};
pack_primitive(&mut fimg, &dat, load_addr, typ)?;
println!("{}",fimg.to_json(Some(2)));
println!("{}",fimg.to_json(cmd.get_one::<u16>("indent").copied()));
Ok(())
}

Expand Down
Loading

0 comments on commit 1844656

Please sign in to comment.