From 045f2c5d0a527e58eafba654b3108b21a4832078 Mon Sep 17 00:00:00 2001 From: Andrii Yurchuk Date: Fri, 19 Mar 2021 11:25:39 +0100 Subject: [PATCH] Add --columns option to lists (#76) * Add --columns option to lists * Run actions always * Revert "Run actions always" This reverts commit 403e9e348e10ec58bdfb41afc40ffb44bbdb6d2d. * Add columns option to modality list * Add more tests * And more * Make it nicer * Add another unit test --- Cargo.toml | 2 +- completion/_orthanc | 24 ++ completion/orthanc.bash | 120 +++++++- completion/orthanc.fish | 12 + src/cli.rs | 180 ++++++++++++ src/constants.rs | 32 +-- src/lib.rs | 252 +++++++++++------ src/main.rs | 59 +++- src/utils.rs | 256 +++++++++++++++--- tests/data/all_help.stdout | 83 ++++-- tests/data/instance_list_columns.stdout | 15 + tests/data/instances_search_error.stderr | 2 + tests/data/modality_list_columns.stdout | 4 + tests/data/patient_list_columns.stdout | 4 + tests/data/series_list_columns.stdout | 8 + tests/data/study_list_columns.stdout | 5 + tests/data/unit/list_instances_columns | 4 + .../unit/list_instances_columns_no_header | 2 + tests/data/unit/list_patients_columns | 4 + .../data/unit/list_patients_columns_no_header | 2 + tests/test.rs | 79 ++++++ 21 files changed, 964 insertions(+), 185 deletions(-) create mode 100644 tests/data/instance_list_columns.stdout create mode 100644 tests/data/instances_search_error.stderr create mode 100644 tests/data/modality_list_columns.stdout create mode 100644 tests/data/patient_list_columns.stdout create mode 100644 tests/data/series_list_columns.stdout create mode 100644 tests/data/study_list_columns.stdout create mode 100644 tests/data/unit/list_instances_columns create mode 100644 tests/data/unit/list_instances_columns_no_header create mode 100644 tests/data/unit/list_patients_columns create mode 100644 tests/data/unit/list_patients_columns_no_header diff --git a/Cargo.toml b/Cargo.toml index e899a55..ac38e6d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,7 +31,7 @@ tempfile = "3.2" zip = "0.5" # https://github.com/colin-kiegel/rust-pretty-assertions/issues/19#issuecomment-657672143 -[profile.dev.package.difference] +[profile.dev.package.diff] opt-level = 3 [build-dependencies] diff --git a/completion/_orthanc b/completion/_orthanc index 0c9ab1a..5619347 100644 --- a/completion/_orthanc +++ b/completion/_orthanc @@ -51,6 +51,8 @@ case $state in case $line[1] in (list) _arguments "${_arguments_options[@]}" \ +'*-c+[Display only the columns specified. Space-separated values. Example: ID PatientName]' \ +'*--columns=[Display only the columns specified. Space-separated values. Example: ID PatientName]' \ '-n[Don'\''t display table header]' \ '--no-header[Don'\''t display table header]' \ '-h[Prints help information]' \ @@ -70,6 +72,8 @@ _arguments "${_arguments_options[@]}" \ ;; (list-studies) _arguments "${_arguments_options[@]}" \ +'*-c+[Display only the columns specified. Space-separated values. Example: ID AccessionNumber StudyDate]' \ +'*--columns=[Display only the columns specified. Space-separated values. Example: ID AccessionNumber StudyDate]' \ '-n[Don'\''t display table header]' \ '--no-header[Don'\''t display table header]' \ '-h[Prints help information]' \ @@ -83,6 +87,8 @@ _arguments "${_arguments_options[@]}" \ _arguments "${_arguments_options[@]}" \ '*-q+[Search query terms. Space-separted pairs TagName=TagValue. Wildcards are allowed. Example: PatientSex=F PatientName=*Sanchez*]' \ '*--query=[Search query terms. Space-separted pairs TagName=TagValue. Wildcards are allowed. Example: PatientSex=F PatientName=*Sanchez*]' \ +'*-c+[Display only the columns specified. Space-separated values. Example: ID PatientName]' \ +'*--columns=[Display only the columns specified. Space-separated values. Example: ID PatientName]' \ '-n[Don'\''t display table header]' \ '--no-header[Don'\''t display table header]' \ '-h[Prints help information]' \ @@ -164,6 +170,8 @@ case $state in case $line[1] in (list) _arguments "${_arguments_options[@]}" \ +'*-c+[Display only the columns specified. Space-separated values. Example: ID AccessionNumber StudyDate]' \ +'*--columns=[Display only the columns specified. Space-separated values. Example: ID AccessionNumber StudyDate]' \ '-n[Don'\''t display table header]' \ '--no-header[Don'\''t display table header]' \ '-h[Prints help information]' \ @@ -183,6 +191,8 @@ _arguments "${_arguments_options[@]}" \ ;; (list-series) _arguments "${_arguments_options[@]}" \ +'*-c+[Display only the columns specified. Space-separated values. Example: ID Modality BodyPartExamined]' \ +'*--columns=[Display only the columns specified. Space-separated values. Example: ID Modality BodyPartExamined]' \ '-n[Don'\''t display table header]' \ '--no-header[Don'\''t display table header]' \ '-h[Prints help information]' \ @@ -196,6 +206,8 @@ _arguments "${_arguments_options[@]}" \ _arguments "${_arguments_options[@]}" \ '*-q+[Search query terms. Space-separted pairs TagName=TagValue. Wildcards are allowed. Example: StudyDescription=*BRAIN* StudyDate=20200101]' \ '*--query=[Search query terms. Space-separted pairs TagName=TagValue. Wildcards are allowed. Example: StudyDescription=*BRAIN* StudyDate=20200101]' \ +'*-c+[Display only the columns specified. Space-separated values. Example: ID AccessionNumber StudyDate]' \ +'*--columns=[Display only the columns specified. Space-separated values. Example: ID AccessionNumber StudyDate]' \ '-n[Don'\''t display table header]' \ '--no-header[Don'\''t display table header]' \ '-h[Prints help information]' \ @@ -277,6 +289,8 @@ case $state in case $line[1] in (list) _arguments "${_arguments_options[@]}" \ +'*-c+[Display only the columns specified. Space-separated values. Example: ID Modality BodyPartExamined]' \ +'*--columns=[Display only the columns specified. Space-separated values. Example: ID Modality BodyPartExamined]' \ '-n[Don'\''t display table header]' \ '--no-header[Don'\''t display table header]' \ '-h[Prints help information]' \ @@ -296,6 +310,8 @@ _arguments "${_arguments_options[@]}" \ ;; (list-instances) _arguments "${_arguments_options[@]}" \ +'*-c+[Display only the columns specified. Space-separated values. Example: ID InstanceCreationDate]' \ +'*--columns=[Display only the columns specified. Space-separated values. Example: ID InstanceCreationDate]' \ '-n[Don'\''t display table header]' \ '--no-header[Don'\''t display table header]' \ '-h[Prints help information]' \ @@ -309,6 +325,8 @@ _arguments "${_arguments_options[@]}" \ _arguments "${_arguments_options[@]}" \ '*-q+[Search query terms. Space-separted pairs TagName=TagValue. Wildcards are allowed. Example: SeriesDescription=*BRAIN* SeriesDate=20200101]' \ '*--query=[Search query terms. Space-separted pairs TagName=TagValue. Wildcards are allowed. Example: SeriesDescription=*BRAIN* SeriesDate=20200101]' \ +'*-c+[Display only the columns specified. Space-separated values. Example: ID Modality BodyPartExamined]' \ +'*--columns=[Display only the columns specified. Space-separated values. Example: ID Modality BodyPartExamined]' \ '-n[Don'\''t display table header]' \ '--no-header[Don'\''t display table header]' \ '-h[Prints help information]' \ @@ -390,6 +408,8 @@ case $state in case $line[1] in (list) _arguments "${_arguments_options[@]}" \ +'*-c+[Display only the columns specified. Space-separated values. Example: ID InstanceCreationDate]' \ +'*--columns=[Display only the columns specified. Space-separated values. Example: ID InstanceCreationDate]' \ '-n[Don'\''t display table header]' \ '--no-header[Don'\''t display table header]' \ '-h[Prints help information]' \ @@ -420,6 +440,8 @@ _arguments "${_arguments_options[@]}" \ _arguments "${_arguments_options[@]}" \ '*-q+[Search query terms. Space-separted pairs TagName=TagValue. Wildcards are allowed. Example: InstanceNumber=42 InstanceCreationTime=174242]' \ '*--query=[Search query terms. Space-separted pairs TagName=TagValue. Wildcards are allowed. Example: InstanceNumber=42 InstanceCreationTime=174242]' \ +'*-c+[Display only the columns specified. Space-separated values. Example: ID InstanceCreationDate]' \ +'*--columns=[Display only the columns specified. Space-separated values. Example: ID InstanceCreationDate]' \ '-n[Don'\''t display table header]' \ '--no-header[Don'\''t display table header]' \ '-h[Prints help information]' \ @@ -505,6 +527,8 @@ case $state in case $line[1] in (list) _arguments "${_arguments_options[@]}" \ +'*-c+[Display only the columns specified. Space-separated values. Example: Name Manufacturer]' \ +'*--columns=[Display only the columns specified. Space-separated values. Example: Name Manufacturer]' \ '-n[Don'\''t display table header]' \ '--no-header[Don'\''t display table header]' \ '-h[Prints help information]' \ diff --git a/completion/orthanc.bash b/completion/orthanc.bash index 0fb1da5..d8ca759 100644 --- a/completion/orthanc.bash +++ b/completion/orthanc.bash @@ -235,13 +235,21 @@ _orthanc() { return 0 ;; orthanc__instance__list) - opts=" -n -h -V --no-header --help --version " + opts=" -n -c -h -V --no-header --columns --help --version " if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 fi case "${prev}" in + --columns) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + -c) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -297,7 +305,7 @@ _orthanc() { return 0 ;; orthanc__instance__search) - opts=" -q -n -h -V --query --no-header --help --version " + opts=" -q -n -c -h -V --query --no-header --columns --help --version " if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -312,6 +320,14 @@ _orthanc() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; + --columns) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + -c) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -434,13 +450,21 @@ _orthanc() { return 0 ;; orthanc__modality__list) - opts=" -n -h -V --no-header --help --version " + opts=" -n -c -h -V --no-header --columns --help --version " if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 fi case "${prev}" in + --columns) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + -c) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -618,13 +642,21 @@ _orthanc() { return 0 ;; orthanc__patient__list) - opts=" -n -h -V --no-header --help --version " + opts=" -n -c -h -V --no-header --columns --help --version " if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 fi case "${prev}" in + --columns) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + -c) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -633,13 +665,21 @@ _orthanc() { return 0 ;; orthanc__patient__list__studies) - opts=" -n -h -V --no-header --help --version " + opts=" -n -c -h -V --no-header --columns --help --version " if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 fi case "${prev}" in + --columns) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + -c) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -687,7 +727,7 @@ _orthanc() { return 0 ;; orthanc__patient__search) - opts=" -q -n -h -V --query --no-header --help --version " + opts=" -q -n -c -h -V --query --no-header --columns --help --version " if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -702,6 +742,14 @@ _orthanc() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; + --columns) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + -c) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -817,13 +865,21 @@ _orthanc() { return 0 ;; orthanc__series__list) - opts=" -n -h -V --no-header --help --version " + opts=" -n -c -h -V --no-header --columns --help --version " if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 fi case "${prev}" in + --columns) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + -c) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -832,13 +888,21 @@ _orthanc() { return 0 ;; orthanc__series__list__instances) - opts=" -n -h -V --no-header --help --version " + opts=" -n -c -h -V --no-header --columns --help --version " if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 fi case "${prev}" in + --columns) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + -c) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -886,7 +950,7 @@ _orthanc() { return 0 ;; orthanc__series__search) - opts=" -q -n -h -V --query --no-header --help --version " + opts=" -q -n -c -h -V --query --no-header --columns --help --version " if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -901,6 +965,14 @@ _orthanc() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; + --columns) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + -c) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -1016,13 +1088,21 @@ _orthanc() { return 0 ;; orthanc__study__list) - opts=" -n -h -V --no-header --help --version " + opts=" -n -c -h -V --no-header --columns --help --version " if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 fi case "${prev}" in + --columns) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + -c) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -1031,13 +1111,21 @@ _orthanc() { return 0 ;; orthanc__study__list__series) - opts=" -n -h -V --no-header --help --version " + opts=" -n -c -h -V --no-header --columns --help --version " if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 fi case "${prev}" in + --columns) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + -c) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -1085,7 +1173,7 @@ _orthanc() { return 0 ;; orthanc__study__search) - opts=" -q -n -h -V --query --no-header --help --version " + opts=" -q -n -c -h -V --query --no-header --columns --help --version " if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -1100,6 +1188,14 @@ _orthanc() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; + --columns) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; + -c) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; diff --git a/completion/orthanc.fish b/completion/orthanc.fish index 1eaf9f0..ea778a0 100644 --- a/completion/orthanc.fish +++ b/completion/orthanc.fish @@ -19,6 +19,7 @@ complete -c orthanc -n "__fish_seen_subcommand_from patient" -f -a "anonymize" - complete -c orthanc -n "__fish_seen_subcommand_from patient" -f -a "modify" -d 'Modify patient' complete -c orthanc -n "__fish_seen_subcommand_from patient" -f -a "download" -d 'Download patient' complete -c orthanc -n "__fish_seen_subcommand_from patient" -f -a "delete" -d 'Delete patient' +complete -c orthanc -n "__fish_seen_subcommand_from list" -s c -l columns -d 'Display only the columns specified. Space-separated values. Example: ID PatientName' -r complete -c orthanc -n "__fish_seen_subcommand_from list" -s n -l no-header -d 'Don\'t display table header' complete -c orthanc -n "__fish_seen_subcommand_from list" -s h -l help -d 'Prints help information' complete -c orthanc -n "__fish_seen_subcommand_from list" -s V -l version -d 'Prints version information' @@ -26,10 +27,12 @@ complete -c orthanc -n "__fish_seen_subcommand_from show" -d 'Patient ID' -r complete -c orthanc -n "__fish_seen_subcommand_from show" -s h -l help -d 'Prints help information' complete -c orthanc -n "__fish_seen_subcommand_from show" -s V -l version -d 'Prints version information' complete -c orthanc -n "__fish_seen_subcommand_from list-studies" -d 'Patient ID' -r +complete -c orthanc -n "__fish_seen_subcommand_from list-studies" -s c -l columns -d 'Display only the columns specified. Space-separated values. Example: ID AccessionNumber StudyDate' -r complete -c orthanc -n "__fish_seen_subcommand_from list-studies" -s n -l no-header -d 'Don\'t display table header' complete -c orthanc -n "__fish_seen_subcommand_from list-studies" -s h -l help -d 'Prints help information' complete -c orthanc -n "__fish_seen_subcommand_from list-studies" -s V -l version -d 'Prints version information' complete -c orthanc -n "__fish_seen_subcommand_from search" -s q -l query -d 'Search query terms. Space-separted pairs TagName=TagValue. Wildcards are allowed. Example: PatientSex=F PatientName=*Sanchez*' -r +complete -c orthanc -n "__fish_seen_subcommand_from search" -s c -l columns -d 'Display only the columns specified. Space-separated values. Example: ID PatientName' -r complete -c orthanc -n "__fish_seen_subcommand_from search" -s n -l no-header -d 'Don\'t display table header' complete -c orthanc -n "__fish_seen_subcommand_from search" -s h -l help -d 'Prints help information' complete -c orthanc -n "__fish_seen_subcommand_from search" -s V -l version -d 'Prints version information' @@ -63,6 +66,7 @@ complete -c orthanc -n "__fish_seen_subcommand_from study" -f -a "anonymize" -d complete -c orthanc -n "__fish_seen_subcommand_from study" -f -a "modify" -d 'Modify study' complete -c orthanc -n "__fish_seen_subcommand_from study" -f -a "download" -d 'Download study' complete -c orthanc -n "__fish_seen_subcommand_from study" -f -a "delete" -d 'Delete study' +complete -c orthanc -n "__fish_seen_subcommand_from list" -s c -l columns -d 'Display only the columns specified. Space-separated values. Example: ID AccessionNumber StudyDate' -r complete -c orthanc -n "__fish_seen_subcommand_from list" -s n -l no-header -d 'Don\'t display table header' complete -c orthanc -n "__fish_seen_subcommand_from list" -s h -l help -d 'Prints help information' complete -c orthanc -n "__fish_seen_subcommand_from list" -s V -l version -d 'Prints version information' @@ -70,10 +74,12 @@ complete -c orthanc -n "__fish_seen_subcommand_from show" -d 'Study ID' -r complete -c orthanc -n "__fish_seen_subcommand_from show" -s h -l help -d 'Prints help information' complete -c orthanc -n "__fish_seen_subcommand_from show" -s V -l version -d 'Prints version information' complete -c orthanc -n "__fish_seen_subcommand_from list-series" -d 'Study ID' -r +complete -c orthanc -n "__fish_seen_subcommand_from list-series" -s c -l columns -d 'Display only the columns specified. Space-separated values. Example: ID Modality BodyPartExamined' -r complete -c orthanc -n "__fish_seen_subcommand_from list-series" -s n -l no-header -d 'Don\'t display table header' complete -c orthanc -n "__fish_seen_subcommand_from list-series" -s h -l help -d 'Prints help information' complete -c orthanc -n "__fish_seen_subcommand_from list-series" -s V -l version -d 'Prints version information' complete -c orthanc -n "__fish_seen_subcommand_from search" -s q -l query -d 'Search query terms. Space-separted pairs TagName=TagValue. Wildcards are allowed. Example: StudyDescription=*BRAIN* StudyDate=20200101' -r +complete -c orthanc -n "__fish_seen_subcommand_from search" -s c -l columns -d 'Display only the columns specified. Space-separated values. Example: ID AccessionNumber StudyDate' -r complete -c orthanc -n "__fish_seen_subcommand_from search" -s n -l no-header -d 'Don\'t display table header' complete -c orthanc -n "__fish_seen_subcommand_from search" -s h -l help -d 'Prints help information' complete -c orthanc -n "__fish_seen_subcommand_from search" -s V -l version -d 'Prints version information' @@ -107,6 +113,7 @@ complete -c orthanc -n "__fish_seen_subcommand_from series" -f -a "anonymize" -d complete -c orthanc -n "__fish_seen_subcommand_from series" -f -a "modify" -d 'Modify series' complete -c orthanc -n "__fish_seen_subcommand_from series" -f -a "download" -d 'Download series' complete -c orthanc -n "__fish_seen_subcommand_from series" -f -a "delete" -d 'Delete series' +complete -c orthanc -n "__fish_seen_subcommand_from list" -s c -l columns -d 'Display only the columns specified. Space-separated values. Example: ID Modality BodyPartExamined' -r complete -c orthanc -n "__fish_seen_subcommand_from list" -s n -l no-header -d 'Don\'t display table header' complete -c orthanc -n "__fish_seen_subcommand_from list" -s h -l help -d 'Prints help information' complete -c orthanc -n "__fish_seen_subcommand_from list" -s V -l version -d 'Prints version information' @@ -114,10 +121,12 @@ complete -c orthanc -n "__fish_seen_subcommand_from show" -d 'Series ID' -r complete -c orthanc -n "__fish_seen_subcommand_from show" -s h -l help -d 'Prints help information' complete -c orthanc -n "__fish_seen_subcommand_from show" -s V -l version -d 'Prints version information' complete -c orthanc -n "__fish_seen_subcommand_from list-instances" -d 'Series ID' -r +complete -c orthanc -n "__fish_seen_subcommand_from list-instances" -s c -l columns -d 'Display only the columns specified. Space-separated values. Example: ID InstanceCreationDate' -r complete -c orthanc -n "__fish_seen_subcommand_from list-instances" -s n -l no-header -d 'Don\'t display table header' complete -c orthanc -n "__fish_seen_subcommand_from list-instances" -s h -l help -d 'Prints help information' complete -c orthanc -n "__fish_seen_subcommand_from list-instances" -s V -l version -d 'Prints version information' complete -c orthanc -n "__fish_seen_subcommand_from search" -s q -l query -d 'Search query terms. Space-separted pairs TagName=TagValue. Wildcards are allowed. Example: SeriesDescription=*BRAIN* SeriesDate=20200101' -r +complete -c orthanc -n "__fish_seen_subcommand_from search" -s c -l columns -d 'Display only the columns specified. Space-separated values. Example: ID Modality BodyPartExamined' -r complete -c orthanc -n "__fish_seen_subcommand_from search" -s n -l no-header -d 'Don\'t display table header' complete -c orthanc -n "__fish_seen_subcommand_from search" -s h -l help -d 'Prints help information' complete -c orthanc -n "__fish_seen_subcommand_from search" -s V -l version -d 'Prints version information' @@ -151,6 +160,7 @@ complete -c orthanc -n "__fish_seen_subcommand_from instance" -f -a "anonymize" complete -c orthanc -n "__fish_seen_subcommand_from instance" -f -a "modify" -d 'Modify instance' complete -c orthanc -n "__fish_seen_subcommand_from instance" -f -a "download" -d 'Download instance' complete -c orthanc -n "__fish_seen_subcommand_from instance" -f -a "delete" -d 'Delete instance' +complete -c orthanc -n "__fish_seen_subcommand_from list" -s c -l columns -d 'Display only the columns specified. Space-separated values. Example: ID InstanceCreationDate' -r complete -c orthanc -n "__fish_seen_subcommand_from list" -s n -l no-header -d 'Don\'t display table header' complete -c orthanc -n "__fish_seen_subcommand_from list" -s h -l help -d 'Prints help information' complete -c orthanc -n "__fish_seen_subcommand_from list" -s V -l version -d 'Prints version information' @@ -161,6 +171,7 @@ complete -c orthanc -n "__fish_seen_subcommand_from tags" -d 'Instance ID' -r complete -c orthanc -n "__fish_seen_subcommand_from tags" -s h -l help -d 'Prints help information' complete -c orthanc -n "__fish_seen_subcommand_from tags" -s V -l version -d 'Prints version information' complete -c orthanc -n "__fish_seen_subcommand_from search" -s q -l query -d 'Search query terms. Space-separted pairs TagName=TagValue. Wildcards are allowed. Example: InstanceNumber=42 InstanceCreationTime=174242' -r +complete -c orthanc -n "__fish_seen_subcommand_from search" -s c -l columns -d 'Display only the columns specified. Space-separated values. Example: ID InstanceCreationDate' -r complete -c orthanc -n "__fish_seen_subcommand_from search" -s n -l no-header -d 'Don\'t display table header' complete -c orthanc -n "__fish_seen_subcommand_from search" -s h -l help -d 'Prints help information' complete -c orthanc -n "__fish_seen_subcommand_from search" -s V -l version -d 'Prints version information' @@ -195,6 +206,7 @@ complete -c orthanc -n "__fish_seen_subcommand_from modality" -f -a "modify" -d complete -c orthanc -n "__fish_seen_subcommand_from modality" -f -a "echo" -d 'Send a C-ECHO request to a modality' complete -c orthanc -n "__fish_seen_subcommand_from modality" -f -a "store" -d 'Send a C-STORE request to a modality' complete -c orthanc -n "__fish_seen_subcommand_from modality" -f -a "delete" -d 'Delete modality' +complete -c orthanc -n "__fish_seen_subcommand_from list" -s c -l columns -d 'Display only the columns specified. Space-separated values. Example: Name Manufacturer' -r complete -c orthanc -n "__fish_seen_subcommand_from list" -s n -l no-header -d 'Don\'t display table header' complete -c orthanc -n "__fish_seen_subcommand_from list" -s h -l help -d 'Prints help information' complete -c orthanc -n "__fish_seen_subcommand_from list" -s V -l version -d 'Prints version information' diff --git a/src/cli.rs b/src/cli.rs index bf0dad9..6d4862b 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -49,6 +49,21 @@ pub fn build_cli() -> App<'static> { .short('n') .long("no-header"), ) + .arg( + Arg::new("columns") + .about( + concat!( + "Display only the columns specified. Space-separated values. ", + "Example: ID PatientName", + ) + ) + .takes_value(true) + .short('c') + .long("columns") + .multiple_occurrences(true) + .multiple_values(true) + .value_name("COLUMNS"), + ) ) .subcommand( App::new("show") @@ -77,6 +92,21 @@ pub fn build_cli() -> App<'static> { .short('n') .long("no-header"), ) + .arg( + Arg::new("columns") + .about( + concat!( + "Display only the columns specified. Space-separated values. ", + "Example: ID AccessionNumber StudyDate", + ) + ) + .takes_value(true) + .short('c') + .long("columns") + .multiple_occurrences(true) + .multiple_values(true) + .value_name("COLUMNS"), + ) ) .subcommand( App::new("search") @@ -102,6 +132,21 @@ pub fn build_cli() -> App<'static> { .short('n') .long("no-header"), ) + .arg( + Arg::new("columns") + .about( + concat!( + "Display only the columns specified. Space-separated values. ", + "Example: ID PatientName", + ) + ) + .takes_value(true) + .short('c') + .long("columns") + .multiple_occurrences(true) + .multiple_values(true) + .value_name("COLUMNS"), + ) ) .subcommand( App::new("anonymize") @@ -258,6 +303,21 @@ pub fn build_cli() -> App<'static> { .short('n') .long("no-header"), ) + .arg( + Arg::new("columns") + .about( + concat!( + "Display only the columns specified. Space-separated values. ", + "Example: ID AccessionNumber StudyDate", + ) + ) + .takes_value(true) + .short('c') + .long("columns") + .multiple_occurrences(true) + .multiple_values(true) + .value_name("COLUMNS"), + ) ) .subcommand( App::new("show") @@ -286,6 +346,21 @@ pub fn build_cli() -> App<'static> { .short('n') .long("no-header"), ) + .arg( + Arg::new("columns") + .about( + concat!( + "Display only the columns specified. Space-separated values. ", + "Example: ID Modality BodyPartExamined", + ) + ) + .takes_value(true) + .short('c') + .long("columns") + .multiple_occurrences(true) + .multiple_values(true) + .value_name("COLUMNS"), + ) ) .subcommand( App::new("search") @@ -311,6 +386,21 @@ pub fn build_cli() -> App<'static> { .short('n') .long("no-header"), ) + .arg( + Arg::new("columns") + .about( + concat!( + "Display only the columns specified. Space-separated values. ", + "Example: ID AccessionNumber StudyDate", + ) + ) + .takes_value(true) + .short('c') + .long("columns") + .multiple_occurrences(true) + .multiple_values(true) + .value_name("COLUMNS"), + ) ) .subcommand( App::new("anonymize") @@ -462,6 +552,21 @@ pub fn build_cli() -> App<'static> { .short('n') .long("no-header"), ) + .arg( + Arg::new("columns") + .about( + concat!( + "Display only the columns specified. Space-separated values. ", + "Example: ID Modality BodyPartExamined", + ) + ) + .takes_value(true) + .short('c') + .long("columns") + .multiple_occurrences(true) + .multiple_values(true) + .value_name("COLUMNS"), + ) ) .subcommand( App::new("show") @@ -490,6 +595,21 @@ pub fn build_cli() -> App<'static> { .short('n') .long("no-header"), ) + .arg( + Arg::new("columns") + .about( + concat!( + "Display only the columns specified. Space-separated values. ", + "Example: ID InstanceCreationDate", + ) + ) + .takes_value(true) + .short('c') + .long("columns") + .multiple_occurrences(true) + .multiple_values(true) + .value_name("COLUMNS"), + ) ) .subcommand( App::new("search") @@ -515,6 +635,21 @@ pub fn build_cli() -> App<'static> { .short('n') .long("no-header"), ) + .arg( + Arg::new("columns") + .about( + concat!( + "Display only the columns specified. Space-separated values. ", + "Example: ID Modality BodyPartExamined", + ) + ) + .takes_value(true) + .short('c') + .long("columns") + .multiple_occurrences(true) + .multiple_values(true) + .value_name("COLUMNS"), + ) ) .subcommand( App::new("anonymize") @@ -671,6 +806,21 @@ pub fn build_cli() -> App<'static> { .short('n') .long("no-header"), ) + .arg( + Arg::new("columns") + .about( + concat!( + "Display only the columns specified. Space-separated values. ", + "Example: ID InstanceCreationDate", + ) + ) + .takes_value(true) + .short('c') + .long("columns") + .multiple_occurrences(true) + .multiple_values(true) + .value_name("COLUMNS"), + ) ) .subcommand( App::new("show") @@ -718,6 +868,21 @@ pub fn build_cli() -> App<'static> { .short('n') .long("no-header"), ) + .arg( + Arg::new("columns") + .about( + concat!( + "Display only the columns specified. Space-separated values. ", + "Example: ID InstanceCreationDate", + ) + ) + .takes_value(true) + .short('c') + .long("columns") + .multiple_occurrences(true) + .multiple_values(true) + .value_name("COLUMNS"), + ) ) .subcommand( App::new("anonymize") @@ -891,6 +1056,21 @@ pub fn build_cli() -> App<'static> { .short('n') .long("no-header"), ) + .arg( + Arg::new("columns") + .about( + concat!( + "Display only the columns specified. Space-separated values. ", + "Example: Name Manufacturer", + ) + ) + .takes_value(true) + .short('c') + .long("columns") + .multiple_occurrences(true) + .multiple_values(true) + .value_name("COLUMNS"), + ) ) .subcommand( App::new("show") diff --git a/src/constants.rs b/src/constants.rs index 31990e7..832ecf9 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -2,13 +2,13 @@ pub const TABLE_PRESET: &str = " -- "; pub const ID_COLUMN_WIDTH: u16 = 46; pub const ABSENT_DICOM_TAG_PLACEHOLDER: &str = "undefined"; -pub const PATIENTS_LIST_HEADER: [&str; 4] = - ["ID", "PatientID", "PatientName", "Number of Studies"]; -pub const PATIENTS_LIST_DICOM_TAGS: [&str; 2] = ["PatientID", "PatientName"]; -pub const PATIENT_DICOM_TAGS: [&str; 4] = - ["PatientID", "PatientName", "PatientSex", "PatientBirthDate"]; +pub const PATIENTS_LIST_HEADER: &[&str] = + &["ID", "PatientID", "PatientName", "Number of Studies"]; +pub const PATIENTS_LIST_DICOM_TAGS: &[&str] = &["PatientID", "PatientName"]; +pub const PATIENT_DICOM_TAGS: &[&str] = + &["PatientID", "PatientName", "PatientSex", "PatientBirthDate"]; -pub const STUDIES_LIST_HEADER: [&str; 8] = [ +pub const STUDIES_LIST_HEADER: &[&str] = &[ "ID", "PatientID", "AccessionNumber", @@ -18,7 +18,7 @@ pub const STUDIES_LIST_HEADER: [&str; 8] = [ "StudyTime", "Number of Series", ]; -pub const STUDIES_LIST_DICOM_TAGS: [&str; 6] = [ +pub const STUDIES_LIST_DICOM_TAGS: &[&str] = &[ "PatientID", "AccessionNumber", "StudyInstanceUID", @@ -26,7 +26,7 @@ pub const STUDIES_LIST_DICOM_TAGS: [&str; 6] = [ "StudyDate", "StudyTime", ]; -pub const STUDY_DICOM_TAGS: [&str; 7] = [ +pub const STUDY_DICOM_TAGS: &[&str] = &[ "PatientID", "StudyID", "AccessionNumber", @@ -36,7 +36,7 @@ pub const STUDY_DICOM_TAGS: [&str; 7] = [ "StudyTime", ]; -pub const SERIES_LIST_HEADER: [&str; 6] = [ +pub const SERIES_LIST_HEADER: &[&str] = &[ "ID", "SeriesInstanceUID", "SeriesDescription", @@ -44,13 +44,13 @@ pub const SERIES_LIST_HEADER: [&str; 6] = [ "BodyPartExamined", "Number of Instances", ]; -pub const SERIES_LIST_DICOM_TAGS: [&str; 4] = [ +pub const SERIES_LIST_DICOM_TAGS: &[&str] = &[ "SeriesInstanceUID", "SeriesDescription", "Modality", "BodyPartExamined", ]; -pub const SERIES_DICOM_TAGS: [&str; 5] = [ +pub const SERIES_DICOM_TAGS: &[&str] = &[ "SeriesInstanceUID", "SeriesNumber", "SeriesDescription", @@ -58,7 +58,7 @@ pub const SERIES_DICOM_TAGS: [&str; 5] = [ "BodyPartExamined", ]; -pub const INSTANCES_LIST_HEADER: [&str; 7] = [ +pub const INSTANCES_LIST_HEADER: &[&str] = &[ "ID", "SOPInstanceUID", "InstanceNumber", @@ -67,18 +67,18 @@ pub const INSTANCES_LIST_HEADER: [&str; 7] = [ "Index in series", "File size", ]; -pub const INSTANCES_LIST_DICOM_TAGS: [&str; 4] = [ +pub const INSTANCES_LIST_DICOM_TAGS: &[&str] = &[ "SOPInstanceUID", "InstanceNumber", "InstanceCreationDate", "InstanceCreationTime", ]; -pub const INSTANCE_DICOM_TAGS: [&str; 4] = [ +pub const INSTANCE_DICOM_TAGS: &[&str] = &[ "SOPInstanceUID", "InstanceNumber", "InstanceCreationDate", "InstanceCreationTime", ]; -pub const MODALITIES_LIST_HEADER: [&str; 5] = - ["Name", "AET", "Host", "Port", "Manufacturer"]; +pub const MODALITIES_LIST_HEADER: &[&str] = + &["Name", "AET", "Host", "Port", "Manufacturer"]; diff --git a/src/lib.rs b/src/lib.rs index dcfd6a0..83f03d0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -82,15 +82,20 @@ impl Orthanc { ////////// PATIENT ////////// - pub fn list_patients(&self, no_header: bool) -> Result { + pub fn list_patients( + &self, + columns: Option>, + no_header: bool, + ) -> Result
{ + let header = &mut PATIENTS_LIST_HEADER.to_vec(); + let dicom_tags = &mut PATIENTS_LIST_DICOM_TAGS.to_vec(); + get_header_and_dicom_tags(header, dicom_tags, columns)?; + Ok(utils::create_list_table( self.client.patients_expanded()?, - if no_header { - None - } else { - Some(&PATIENTS_LIST_HEADER) - }, - &PATIENTS_LIST_DICOM_TAGS, + header, + dicom_tags, + no_header, )) } @@ -150,20 +155,28 @@ impl Orthanc { ////////// STUDY ////////// - pub fn list_studies(&self, patient_id: Option<&str>, no_header: bool) -> Result
{ - let mut studies = self.client.studies_expanded()?; + pub fn list_studies( + &self, + patient_id: Option<&str>, + columns: Option>, + no_header: bool, + ) -> Result
{ + let header = &mut STUDIES_LIST_HEADER.to_vec(); + let dicom_tags = &mut STUDIES_LIST_DICOM_TAGS.to_vec(); + get_header_and_dicom_tags(header, dicom_tags, columns)?; + if let Some(pid) = patient_id { self.client.patient(pid)?; // Check if the patient exists + } + + let mut studies = self.client.studies_expanded()?; + + if let Some(pid) = patient_id { studies.retain(|s| s.parent_id().unwrap() == pid); }; - Ok(create_list_table( - studies, - if no_header { - None - } else { - Some(&STUDIES_LIST_HEADER) - }, - &STUDIES_LIST_DICOM_TAGS, + + Ok(utils::create_list_table( + studies, header, dicom_tags, no_header, )) } @@ -223,20 +236,28 @@ impl Orthanc { ////////// SERIES ////////// - pub fn list_series(&self, study_id: Option<&str>, no_header: bool) -> Result
{ + pub fn list_series( + &self, + study_id: Option<&str>, + columns: Option>, + no_header: bool, + ) -> Result
{ + let header = &mut SERIES_LIST_HEADER.to_vec(); + let dicom_tags = &mut SERIES_LIST_DICOM_TAGS.to_vec(); + get_header_and_dicom_tags(header, dicom_tags, columns)?; + + if let Some(pid) = study_id { + self.client.study(pid)?; // Check if the study exists + } + let mut series = self.client.series_expanded()?; + if let Some(sid) = study_id { - self.client.study(sid)?; // Check if the study exists series.retain(|s| s.parent_id().unwrap() == sid); }; - Ok(create_list_table( - series, - if no_header { - None - } else { - Some(&SERIES_LIST_HEADER) - }, - &SERIES_LIST_DICOM_TAGS, + + Ok(utils::create_list_table( + series, header, dicom_tags, no_header, )) } @@ -299,21 +320,25 @@ impl Orthanc { pub fn list_instances( &self, series_id: Option<&str>, + columns: Option>, no_header: bool, ) -> Result
{ + let header = &mut INSTANCES_LIST_HEADER.to_vec(); + let dicom_tags = &mut INSTANCES_LIST_DICOM_TAGS.to_vec(); + get_header_and_dicom_tags(header, dicom_tags, columns)?; + + if let Some(pid) = series_id { + self.client.series(pid)?; // Check if the series exists + } + let mut instances = self.client.instances_expanded()?; + if let Some(sid) = series_id { - self.client.series(sid)?; // Check if the series exists instances.retain(|s| s.parent_id().unwrap() == sid); }; - Ok(create_list_table( - instances, - if no_header { - None - } else { - Some(&INSTANCES_LIST_HEADER) - }, - &INSTANCES_LIST_DICOM_TAGS, + + Ok(utils::create_list_table( + instances, header, dicom_tags, no_header, )) } @@ -424,27 +449,66 @@ impl Orthanc { } } - pub fn list_modalities(&self, no_header: bool) -> Result
{ - let modalities = self.client.modalities_expanded()?; - let header: Option<&[&str]>; - if no_header { - header = None; - } else { - header = Some(&MODALITIES_LIST_HEADER); + pub fn list_modalities( + &self, + columns: Option>, + no_header: bool, + ) -> Result
{ + let header = &mut MODALITIES_LIST_HEADER.to_vec(); + let mut real_header = None; + + if let Some(c) = &columns { + check_columns_option(&header, &c)?; }; - let mut table = create_table(header); - for (m_name, m_config) in modalities { - let row = vec![ - m_name, - m_config.aet, - m_config.host, - format!("{}", m_config.port), - m_config.manufacturer.unwrap(), - ]; - table.add_row(row.iter()); + let modalities = self.client.modalities_expanded()?; + + if let Some(c) = columns { + // Make sure that the columns are sorted in the same way as the original header + header.retain(|v| c.contains(v)); + + if !no_header { + real_header = Some(&header); + }; + + let mut table = create_table(real_header.map(|v| v.as_ref())); + for (m_name, m_config) in modalities { + let mut row = vec![]; + if header.contains(&"Name") { + row.push(m_name); + }; + if header.contains(&"AET") { + row.push(m_config.aet); + }; + if header.contains(&"Host") { + row.push(m_config.host); + }; + if header.contains(&"Port") { + row.push(format!("{}", m_config.port)); + }; + if header.contains(&"Manufacturer") { + row.push(m_config.manufacturer.unwrap()); + }; + table.add_row(row.iter()); + } + Ok(table) + } else { + if !no_header { + real_header = Some(&header); + }; + let mut table = create_table(real_header.map(|v| v.as_ref())); + for (m_name, m_config) in modalities { + let row = vec![ + m_name, + m_config.aet, + m_config.host, + format!("{}", m_config.port), + m_config.manufacturer.unwrap(), + ]; + table.add_row(row.iter()); + } + Ok(table) } - Ok(table) } pub fn show_modality(&self, name: &str) -> Result
{ @@ -557,55 +621,71 @@ impl Orthanc { self.client.delete_modality(name).map_err(Into::<_>::into) } - pub fn search_patients(&self, query: Vec<&str>, no_header: bool) -> Result
{ + pub fn search_patients( + &self, + query: Vec<&str>, + columns: Option>, + no_header: bool, + ) -> Result
{ + let header = &mut PATIENTS_LIST_HEADER.to_vec(); + let dicom_tags = &mut PATIENTS_LIST_DICOM_TAGS.to_vec(); + get_header_and_dicom_tags(header, dicom_tags, columns)?; + let patients: Vec = self.client.search(parse_tag_kv_pairs(query)?)?; + Ok(utils::create_list_table( - patients, - if no_header { - None - } else { - Some(&PATIENTS_LIST_HEADER) - }, - &PATIENTS_LIST_DICOM_TAGS, + patients, header, dicom_tags, no_header, )) } - pub fn search_studies(&self, query: Vec<&str>, no_header: bool) -> Result
{ + pub fn search_studies( + &self, + query: Vec<&str>, + columns: Option>, + no_header: bool, + ) -> Result
{ + let header = &mut STUDIES_LIST_HEADER.to_vec(); + let dicom_tags = &mut STUDIES_LIST_DICOM_TAGS.to_vec(); + get_header_and_dicom_tags(header, dicom_tags, columns)?; + let studies: Vec = self.client.search(parse_tag_kv_pairs(query)?)?; + Ok(utils::create_list_table( - studies, - if no_header { - None - } else { - Some(&STUDIES_LIST_HEADER) - }, - &STUDIES_LIST_DICOM_TAGS, + studies, header, dicom_tags, no_header, )) } - pub fn search_series(&self, query: Vec<&str>, no_header: bool) -> Result
{ + pub fn search_series( + &self, + query: Vec<&str>, + columns: Option>, + no_header: bool, + ) -> Result
{ + let header = &mut SERIES_LIST_HEADER.to_vec(); + let dicom_tags = &mut SERIES_LIST_DICOM_TAGS.to_vec(); + get_header_and_dicom_tags(header, dicom_tags, columns)?; + let series: Vec = self.client.search(parse_tag_kv_pairs(query)?)?; + Ok(utils::create_list_table( - series, - if no_header { - None - } else { - Some(&SERIES_LIST_HEADER) - }, - &SERIES_LIST_DICOM_TAGS, + series, header, dicom_tags, no_header, )) } - pub fn search_instances(&self, query: Vec<&str>, no_header: bool) -> Result
{ + pub fn search_instances( + &self, + query: Vec<&str>, + columns: Option>, + no_header: bool, + ) -> Result
{ + let header = &mut INSTANCES_LIST_HEADER.to_vec(); + let dicom_tags = &mut INSTANCES_LIST_DICOM_TAGS.to_vec(); + get_header_and_dicom_tags(header, dicom_tags, columns)?; + let instances: Vec = self.client.search(parse_tag_kv_pairs(query)?)?; + Ok(utils::create_list_table( - instances, - if no_header { - None - } else { - Some(&INSTANCES_LIST_HEADER) - }, - &INSTANCES_LIST_DICOM_TAGS, + instances, header, dicom_tags, no_header, )) } } diff --git a/src/main.rs b/src/main.rs index c93969e..75035a3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -21,7 +21,10 @@ fn main() { match matches.subcommand() { Some(("patient", patient)) => match patient.subcommand() { - Some(("list", list)) => match o.list_patients(list.is_present("no_header")) { + Some(("list", list)) => match o.list_patients( + list.values_of("columns").map(|c| c.collect()), + list.is_present("no_header"), + ) { Ok(t) => print_table(t), Err(e) => exit_with_error(e), }, @@ -32,6 +35,7 @@ fn main() { Some(("list-studies", list_studies)) => { match o.list_studies( list_studies.value_of("id"), + list_studies.values_of("columns").map(|c| c.collect()), list_studies.is_present("no_header"), ) { Ok(t) => print_table(t), @@ -55,8 +59,11 @@ fn main() { } } Some(("search", search)) => { - let terms: Vec<&str> = search.values_of("query").unwrap().collect(); - match o.search_patients(terms, search.is_present("no_header")) { + match o.search_patients( + search.values_of("query").unwrap().collect(), + search.values_of("columns").map(|c| c.collect()), + search.is_present("no_header"), + ) { Ok(t) => print_table(t), Err(e) => exit_with_error(e), } @@ -87,7 +94,11 @@ fn main() { }, Some(("study", study)) => match study.subcommand() { Some(("list", list)) => { - match o.list_studies(None, list.is_present("no_header")) { + match o.list_studies( + None, + list.values_of("columns").map(|c| c.collect()), + list.is_present("no_header"), + ) { Ok(t) => print_table(t), Err(e) => exit_with_error(e), } @@ -99,6 +110,7 @@ fn main() { Some(("list-series", list_series)) => { match o.list_series( list_series.value_of("id"), + list_series.values_of("columns").map(|c| c.collect()), list_series.is_present("no_header"), ) { Ok(t) => print_table(t), @@ -106,8 +118,11 @@ fn main() { } } Some(("search", search)) => { - let terms: Vec<&str> = search.values_of("query").unwrap().collect(); - match o.search_studies(terms, search.is_present("no_header")) { + match o.search_studies( + search.values_of("query").unwrap().collect(), + search.values_of("columns").map(|c| c.collect()), + search.is_present("no_header"), + ) { Ok(t) => print_table(t), Err(e) => exit_with_error(e), } @@ -154,7 +169,11 @@ fn main() { }, Some(("series", series)) => match series.subcommand() { Some(("list", list)) => { - match o.list_series(None, list.is_present("no_header")) { + match o.list_series( + None, + list.values_of("columns").map(|c| c.collect()), + list.is_present("no_header"), + ) { Ok(t) => print_table(t), Err(e) => exit_with_error(e), } @@ -166,6 +185,7 @@ fn main() { Some(("list-instances", list_instances)) => { match o.list_instances( list_instances.value_of("id"), + list_instances.values_of("columns").map(|c| c.collect()), list_instances.is_present("no_header"), ) { Ok(t) => print_table(t), @@ -173,8 +193,11 @@ fn main() { } } Some(("search", search)) => { - let terms: Vec<&str> = search.values_of("query").unwrap().collect(); - match o.search_series(terms, search.is_present("no_header")) { + match o.search_series( + search.values_of("query").unwrap().collect(), + search.values_of("columns").map(|c| c.collect()), + search.is_present("no_header"), + ) { Ok(t) => print_table(t), Err(e) => exit_with_error(e), } @@ -221,7 +244,11 @@ fn main() { }, Some(("instance", instance)) => match instance.subcommand() { Some(("list", list)) => { - match o.list_instances(None, list.is_present("no_header")) { + match o.list_instances( + None, + list.values_of("columns").map(|c| c.collect()), + list.is_present("no_header"), + ) { Ok(t) => print_table(t), Err(e) => exit_with_error(e), } @@ -231,8 +258,11 @@ fn main() { Err(e) => exit_with_error(e), }, Some(("search", search)) => { - let terms: Vec<&str> = search.values_of("query").unwrap().collect(); - match o.search_instances(terms, search.is_present("no_header")) { + match o.search_instances( + search.values_of("query").unwrap().collect(), + search.values_of("columns").map(|c| c.collect()), + search.is_present("no_header"), + ) { Ok(t) => print_table(t), Err(e) => exit_with_error(e), } @@ -286,7 +316,10 @@ fn main() { _ => {} }, Some(("modality", modality)) => match modality.subcommand() { - Some(("list", list)) => match o.list_modalities(list.is_present("no_header")) { + Some(("list", list)) => match o.list_modalities( + list.values_of("columns").map(|c| c.collect()), + list.is_present("no_header"), + ) { Ok(t) => print_table(t), Err(e) => exit_with_error(e), }, diff --git a/src/utils.rs b/src/utils.rs index 1d40e8e..212ec96 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -20,39 +20,59 @@ pub fn create_table(header: Option<&[&str]>) -> Table { pub fn create_list_table( entities: Vec, - header: Option<&[&str]>, + columns: &[&str], dicom_tags: &[&str], + no_header: bool, ) -> Table { + let header = if no_header { None } else { Some(columns) }; let mut table = create_table(header); for entity in entities { - let mut row: Vec<&str> = vec![entity.id()]; + let mut row: Vec = vec![]; + + if columns.contains(&"ID") { + row.push(entity.id().to_string()); + }; + for t in dicom_tags.iter() { let val = entity .main_dicom_tag(t) .unwrap_or(ABSENT_DICOM_TAG_PLACEHOLDER); - row.push(val); + row.push(val.to_string()); } + match T::kind() { EntityKind::Instance => { - let index_in_series = match entity.index() { - Some(i) => format!("{}", i), - None => "".to_string(), + if columns.contains(&"Index in series") { + let index_in_series = match entity.index() { + Some(i) => format!("{}", i), + None => "".to_string(), + }; + row.push(index_in_series); + }; + if columns.contains(&"File size") { + let file_size = format!("{}", entity.size()); + row.push(file_size); }; - let file_size = format!("{}", entity.size()); - row.push(&index_in_series); - row.push(&file_size); - table.add_row(row.iter()); } _ => { - let num_children = format!("{}", entity.children_len()); - row.push(&num_children); - table.add_row(row.iter()); + if columns.contains(&"Number of Studies") + || columns.contains(&"Number of Series") + || columns.contains(&"Number of Instances") + { + let num_children = format!("{}", entity.children_len()); + row.push(num_children); + } } } + table.add_row(row.iter()); } - if let Some(id_column) = table.get_column_mut(0) { - id_column.set_constraint(ColumnConstraint::MinWidth(ID_COLUMN_WIDTH)); - } + + // This assumes the ID is always the first column + if columns.contains(&"ID") { + if let Some(id_column) = table.get_column_mut(0) { + id_column.set_constraint(ColumnConstraint::MinWidth(ID_COLUMN_WIDTH)); + } + }; table } @@ -291,6 +311,39 @@ pub fn get_password(cmd_option: Option<&str>) -> Option { } } +pub fn check_columns_option( + original_header: &[&str], + requested_columns: &[&str], +) -> Result<()> { + for c in requested_columns { + if !original_header.contains(c) { + return Err(CliError::new( + "Command error", + Some(&format!( + "Invalid column name: {}. Available columns: {}", + c, + original_header.join(", ") + )), + None, + )); + } + } + Ok(()) +} + +pub fn get_header_and_dicom_tags( + header: &mut Vec<&str>, + dicom_tags: &mut Vec<&str>, + columns: Option>, +) -> Result<()> { + if let Some(c) = columns { + check_columns_option(header, &c)?; + header.retain(|v| c.contains(v)); + dicom_tags.retain(|v| c.contains(v)); + }; + Ok(()) +} + pub fn print_table(table: Table) { println!("{}", table); } @@ -333,7 +386,12 @@ mod tests { assert_eq!(&format!("{}", table), ""); } - fn test_list_table_patient(header: Option<&[&str]>, expected_output: &str) { + fn test_list_table_patient( + columns: &[&str], + dicom_tags: &[&str], + no_header: bool, + expected_output: &str, + ) { let patient_1 = Patient { id: "foo".to_string(), is_stable: true, @@ -360,14 +418,20 @@ mod tests { assert_eq!( format_table(create_list_table( vec![patient_1, patient_2], - header, - &PATIENTS_LIST_DICOM_TAGS, + &columns, + &dicom_tags, + no_header, )), expected_output ); } - fn test_list_table_study(header: Option<&[&str]>, expected_output: &str) { + fn test_list_table_study( + columns: &[&str], + dicom_tags: &[&str], + no_header: bool, + expected_output: &str, + ) { let study_1 = Study { id: "foo".to_string(), is_stable: true, @@ -405,14 +469,20 @@ mod tests { assert_eq!( format_table(create_list_table( vec![study_1, study_2], - header, - &STUDIES_LIST_DICOM_TAGS, + &columns, + &dicom_tags, + no_header, )), expected_output ); } - fn test_list_table_series(header: Option<&[&str]>, expected_output: &str) { + fn test_list_table_series( + columns: &[&str], + dicom_tags: &[&str], + no_header: bool, + expected_output: &str, + ) { let series_1 = Series { id: "foo".to_string(), status: "Unknown".to_string(), @@ -446,13 +516,19 @@ mod tests { assert_eq!( format_table(create_list_table( vec![series_1, series_2], - header, - &SERIES_LIST_DICOM_TAGS, + &columns, + &dicom_tags, + no_header, )), expected_output ); } - fn test_list_table_instance(header: Option<&[&str]>, expected_output: &str) { + fn test_list_table_instance( + columns: &[&str], + dicom_tags: &[&str], + no_header: bool, + expected_output: &str, + ) { let instance_1 = Instance { id: "foo".to_string(), main_dicom_tags: hashmap! { @@ -485,8 +561,9 @@ mod tests { assert_eq!( format_table(create_list_table( vec![instance_1, instance_2], - header, - &INSTANCES_LIST_DICOM_TAGS, + &columns, + &dicom_tags, + no_header, )), expected_output ); @@ -495,7 +572,9 @@ mod tests { #[test] fn test_create_list_table_patient() { test_list_table_patient( - Some(&PATIENTS_LIST_HEADER), + PATIENTS_LIST_HEADER, + PATIENTS_LIST_DICOM_TAGS, + false, include_str!("../tests/data/unit/list_patients").trim_end(), ); } @@ -503,15 +582,39 @@ mod tests { #[test] fn test_create_list_table_patient_no_header() { test_list_table_patient( - None, + PATIENTS_LIST_HEADER, + PATIENTS_LIST_DICOM_TAGS, + true, include_str!("../tests/data/unit/list_patients_no_header").trim_end(), ); } + #[test] + fn test_create_list_table_patient_columns() { + test_list_table_patient( + &["PatientID", "Number of Studies"], + &["PatientID"], + false, + include_str!("../tests/data/unit/list_patients_columns").trim_end(), + ); + } + + #[test] + fn test_create_list_table_patient_columns_no_header() { + test_list_table_patient( + &["PatientID", "Number of Studies"], + &["PatientID"], + true, + include_str!("../tests/data/unit/list_patients_columns_no_header").trim_end(), + ); + } + #[test] fn test_create_list_table_study() { test_list_table_study( - Some(&STUDIES_LIST_HEADER), + STUDIES_LIST_HEADER, + STUDIES_LIST_DICOM_TAGS, + false, include_str!("../tests/data/unit/list_studies").trim_end(), ); } @@ -519,7 +622,9 @@ mod tests { #[test] fn test_create_list_table_study_no_header() { test_list_table_study( - None, + STUDIES_LIST_HEADER, + STUDIES_LIST_DICOM_TAGS, + true, include_str!("../tests/data/unit/list_studies_no_header").trim_end(), ); } @@ -527,7 +632,9 @@ mod tests { #[test] fn test_create_list_table_series() { test_list_table_series( - Some(&SERIES_LIST_HEADER), + SERIES_LIST_HEADER, + SERIES_LIST_DICOM_TAGS, + false, include_str!("../tests/data/unit/list_series").trim_end(), ); } @@ -535,7 +642,9 @@ mod tests { #[test] fn test_create_list_table_series_no_header() { test_list_table_series( - None, + SERIES_LIST_HEADER, + SERIES_LIST_DICOM_TAGS, + true, include_str!("../tests/data/unit/list_series_no_header").trim_end(), ); } @@ -543,7 +652,9 @@ mod tests { #[test] fn test_create_list_table_instance() { test_list_table_instance( - Some(&INSTANCES_LIST_HEADER), + INSTANCES_LIST_HEADER, + INSTANCES_LIST_DICOM_TAGS, + false, include_str!("../tests/data/unit/list_instances").trim_end(), ); } @@ -551,16 +662,43 @@ mod tests { #[test] fn test_create_list_table_instance_no_header() { test_list_table_instance( - None, + INSTANCES_LIST_HEADER, + INSTANCES_LIST_DICOM_TAGS, + true, include_str!("../tests/data/unit/list_instances_no_header").trim_end(), ); } + #[test] + fn test_create_list_table_instance_columns() { + test_list_table_instance( + &["SOPInstanceUID", "Index in series", "File size"], + &["SOPInstanceUID"], + false, + include_str!("../tests/data/unit/list_instances_columns").trim_end(), + ); + } + + #[test] + fn test_create_list_table_instance_columns_no_header() { + test_list_table_instance( + &["SOPInstanceUID", "Index in series", "File size"], + &["SOPInstanceUID"], + true, + include_str!("../tests/data/unit/list_instances_columns_no_header").trim_end(), + ); + } + #[test] fn test_create_list_table_no_header_no_data() { let data: Vec = vec![]; assert_eq!( - format_table(create_list_table(data, None, &PATIENTS_LIST_DICOM_TAGS)), + format_table(create_list_table( + data, + PATIENTS_LIST_HEADER, + PATIENTS_LIST_DICOM_TAGS, + true, + )), "" ); } @@ -946,4 +1084,48 @@ mod tests { assert_eq!(get_password(Some("foo")).unwrap(), "foo".to_string()); assert_eq!(get_password(None).unwrap(), "bar".to_string()); } + + #[test] + fn test_check_columns_options() { + assert_eq!( + check_columns_option(&["foo", "bar", "baz"], &["foo", "baz"]).unwrap(), + () + ); + + assert_eq!( + check_columns_option(&["foo", "bar", "baz"], &["bar", "qux"]).unwrap_err(), + CliError::new( + "Command error", + Some("Invalid column name: qux. Available columns: foo, bar, baz"), + None + ) + ) + } + + #[test] + fn test_get_header_and_dicom_tags() { + let mut header = vec!["foo", "bar", "baz", "qux", "quux", "quuz"]; + let mut dicom_tags = vec!["qux", "quux", "quuz"]; + + get_header_and_dicom_tags( + &mut header, + &mut dicom_tags, + Some(vec!["bar", "quux", "quuz"]), + ) + .unwrap(); + + assert_eq!(header, vec!["bar", "quux", "quuz"]); + assert_eq!(dicom_tags, vec!["quux", "quuz"]); + } + + #[test] + fn test_get_header_and_dicom_tags_no_columns() { + let mut header = vec!["foo", "bar", "baz"]; + let mut dicom_tags = vec!["qux", "quux", "quuz"]; + + get_header_and_dicom_tags(&mut header, &mut dicom_tags, None).unwrap(); + + assert_eq!(header, vec!["foo", "bar", "baz"]); + assert_eq!(dicom_tags, vec!["qux", "quux", "quuz"]); + } } diff --git a/tests/data/all_help.stdout b/tests/data/all_help.stdout index 2051d94..6ab31a2 100644 --- a/tests/data/all_help.stdout +++ b/tests/data/all_help.stdout @@ -50,13 +50,17 @@ list List all patients USAGE: - list [FLAGS] + list [FLAGS] [OPTIONS] FLAGS: -h, --help Prints help information -n, --no-header Don't display table header -V, --version Prints version information +OPTIONS: + -c, --columns ... Display only the columns specified. Space-separated values. + Example: ID PatientName + ========== show ========== show Show patient details @@ -76,7 +80,7 @@ list-studies List all studies of a patient USAGE: - list-studies [FLAGS] + list-studies [FLAGS] [OPTIONS] ARGS: Patient ID @@ -86,12 +90,16 @@ FLAGS: -n, --no-header Don't display table header -V, --version Prints version information +OPTIONS: + -c, --columns ... Display only the columns specified. Space-separated values. + Example: ID AccessionNumber StudyDate + ========== search ========== search Search for patients USAGE: - search [FLAGS] --query ... + search [FLAGS] [OPTIONS] --query ... FLAGS: -h, --help Prints help information @@ -99,8 +107,10 @@ FLAGS: -V, --version Prints version information OPTIONS: - -q, --query ... Search query terms. Space-separted pairs TagName=TagValue. Wildcards - are allowed. Example: PatientSex=F PatientName=*Sanchez* + -c, --columns ... Display only the columns specified. Space-separated values. + Example: ID PatientName + -q, --query ... Search query terms. Space-separted pairs TagName=TagValue. + Wildcards are allowed. Example: PatientSex=F PatientName=*Sanchez* ========== anonymize ========== anonymize @@ -216,13 +226,17 @@ list List all studies USAGE: - list [FLAGS] + list [FLAGS] [OPTIONS] FLAGS: -h, --help Prints help information -n, --no-header Don't display table header -V, --version Prints version information +OPTIONS: + -c, --columns ... Display only the columns specified. Space-separated values. + Example: ID AccessionNumber StudyDate + ========== show ========== show Show study details @@ -242,7 +256,7 @@ list-series List all series of a study USAGE: - list-series [FLAGS] + list-series [FLAGS] [OPTIONS] ARGS: Study ID @@ -252,12 +266,16 @@ FLAGS: -n, --no-header Don't display table header -V, --version Prints version information +OPTIONS: + -c, --columns ... Display only the columns specified. Space-separated values. + Example: ID Modality BodyPartExamined + ========== search ========== search Search for studies USAGE: - search [FLAGS] --query ... + search [FLAGS] [OPTIONS] --query ... FLAGS: -h, --help Prints help information @@ -265,8 +283,11 @@ FLAGS: -V, --version Prints version information OPTIONS: - -q, --query ... Search query terms. Space-separted pairs TagName=TagValue. Wildcards - are allowed. Example: StudyDescription=*BRAIN* StudyDate=20200101 + -c, --columns ... Display only the columns specified. Space-separated values. + Example: ID AccessionNumber StudyDate + -q, --query ... Search query terms. Space-separted pairs TagName=TagValue. + Wildcards are allowed. Example: StudyDescription=*BRAIN* + StudyDate=20200101 ========== anonymize ========== anonymize @@ -382,13 +403,17 @@ list List all series USAGE: - list [FLAGS] + list [FLAGS] [OPTIONS] FLAGS: -h, --help Prints help information -n, --no-header Don't display table header -V, --version Prints version information +OPTIONS: + -c, --columns ... Display only the columns specified. Space-separated values. + Example: ID Modality BodyPartExamined + ========== show ========== show Show series details @@ -408,7 +433,7 @@ list-instances List all instances of a series USAGE: - list-instances [FLAGS] + list-instances [FLAGS] [OPTIONS] ARGS: Series ID @@ -418,12 +443,16 @@ FLAGS: -n, --no-header Don't display table header -V, --version Prints version information +OPTIONS: + -c, --columns ... Display only the columns specified. Space-separated values. + Example: ID InstanceCreationDate + ========== search ========== search Search for series USAGE: - search [FLAGS] --query ... + search [FLAGS] [OPTIONS] --query ... FLAGS: -h, --help Prints help information @@ -431,8 +460,11 @@ FLAGS: -V, --version Prints version information OPTIONS: - -q, --query ... Search query terms. Space-separted pairs TagName=TagValue. Wildcards - are allowed. Example: SeriesDescription=*BRAIN* SeriesDate=20200101 + -c, --columns ... Display only the columns specified. Space-separated values. + Example: ID Modality BodyPartExamined + -q, --query ... Search query terms. Space-separted pairs TagName=TagValue. + Wildcards are allowed. Example: SeriesDescription=*BRAIN* + SeriesDate=20200101 ========== anonymize ========== anonymize @@ -548,13 +580,17 @@ list List all instances USAGE: - list [FLAGS] + list [FLAGS] [OPTIONS] FLAGS: -h, --help Prints help information -n, --no-header Don't display table header -V, --version Prints version information +OPTIONS: + -c, --columns ... Display only the columns specified. Space-separated values. + Example: ID InstanceCreationDate + ========== show ========== show Show instance details @@ -588,7 +624,7 @@ search Search for instances USAGE: - search [FLAGS] --query ... + search [FLAGS] [OPTIONS] --query ... FLAGS: -h, --help Prints help information @@ -596,8 +632,11 @@ FLAGS: -V, --version Prints version information OPTIONS: - -q, --query ... Search query terms. Space-separted pairs TagName=TagValue. Wildcards - are allowed. Example: InstanceNumber=42 InstanceCreationTime=174242 + -c, --columns ... Display only the columns specified. Space-separated values. + Example: ID InstanceCreationDate + -q, --query ... Search query terms. Space-separted pairs TagName=TagValue. + Wildcards are allowed. Example: InstanceNumber=42 + InstanceCreationTime=174242 ========== anonymize ========== anonymize @@ -714,13 +753,17 @@ list List all modalities USAGE: - list [FLAGS] + list [FLAGS] [OPTIONS] FLAGS: -h, --help Prints help information -n, --no-header Don't display table header -V, --version Prints version information +OPTIONS: + -c, --columns ... Display only the columns specified. Space-separated values. + Example: Name Manufacturer + ========== show ========== show Show modality details diff --git a/tests/data/instance_list_columns.stdout b/tests/data/instance_list_columns.stdout new file mode 100644 index 0000000..32aff18 --- /dev/null +++ b/tests/data/instance_list_columns.stdout @@ -0,0 +1,15 @@ + ID InstanceCreationDate +--------------------------------------------------------------------- + c0680933-cc6b1e9d-f1bbb796-f155e4dc-3f321656 20130326 + 4327f23f-661e7f9e-205f6ee0-60137a47-39bc313e 20130326 + 0fdd0f1d-65193336-652071b1-ef69bd02-90b62c3f 20130326 + c791bfaf-6c711120-67734e7c-9fb3e2b3-c33659c9 20130326 + edd7549d-92b00e91-78792e57-5e7322b1-3152956e 20130326 + b611ca1b-5f1ae504-a672cc08-33e5ecf5-8f5b0158 20130326 + 0b62ebce-8ab7b938-e5ca1b05-04802ab3-42ee4307 20130326 + 3677e0e6-c414bdb7-8484cfc5-e1db748f-a0132fab 20130326 + ac584c97-7dd81759-8f7fcabc-ada8ce10-3d34bd0d 20130326 + a35d49de-b62e6943-280a4907-f4480f02-35a8459c 20130326 + c23aa1bd-5f725219-2fc6dc61-a1fc5445-a8a6e974 20130326 + c811a015-f07e7b44-2fd9e3fe-f44a55a6-be4e087a 20130326 + 93166d4d-985a1352-c491bcd8-0b8a672b-7a128d6e 20130326 diff --git a/tests/data/instances_search_error.stderr b/tests/data/instances_search_error.stderr new file mode 100644 index 0000000..70f1630 --- /dev/null +++ b/tests/data/instances_search_error.stderr @@ -0,0 +1,2 @@ + Error Command error + Message Invalid column name: Foo. Available columns: ID, SOPInstanceUID, InstanceNumber, InstanceCreationDate, InstanceCreationTime, Index in series, File size diff --git a/tests/data/modality_list_columns.stdout b/tests/data/modality_list_columns.stdout new file mode 100644 index 0000000..a0afebe --- /dev/null +++ b/tests/data/modality_list_columns.stdout @@ -0,0 +1,4 @@ + Name Manufacturer +--------------------- + bar Generic + foo Generic diff --git a/tests/data/patient_list_columns.stdout b/tests/data/patient_list_columns.stdout new file mode 100644 index 0000000..36f53d9 --- /dev/null +++ b/tests/data/patient_list_columns.stdout @@ -0,0 +1,4 @@ + ID PatientName +------------------------------------------------------------ + 00000000-00000000-00000000-00000000-00000000 Patient 1 + 00000000-00000000-00000000-00000000-00000000 Patient 2 diff --git a/tests/data/series_list_columns.stdout b/tests/data/series_list_columns.stdout new file mode 100644 index 0000000..1cfacd9 --- /dev/null +++ b/tests/data/series_list_columns.stdout @@ -0,0 +1,8 @@ + ID Modality BodyPartExamined +---------------------------------------------------------------------------- + 00000000-00000000-00000000-00000000-00000000 MR ABDOMEN + 00000000-00000000-00000000-00000000-00000000 MR ABDOMEN + 00000000-00000000-00000000-00000000-00000000 MR BRAIN + 00000000-00000000-00000000-00000000-00000000 MR BRAIN + 00000000-00000000-00000000-00000000-00000000 MR KNEE + 00000000-00000000-00000000-00000000-00000000 PR undefined diff --git a/tests/data/study_list_columns.stdout b/tests/data/study_list_columns.stdout new file mode 100644 index 0000000..2dd5e32 --- /dev/null +++ b/tests/data/study_list_columns.stdout @@ -0,0 +1,5 @@ + ID AccessionNumber StudyDate +---------------------------------------------------------------------------- + 00000000-00000000-00000000-00000000-00000000 REMOVED 20110101 + 00000000-00000000-00000000-00000000-00000000 REMOVED 20120101 + 00000000-00000000-00000000-00000000-00000000 REMOVED 20110101 diff --git a/tests/data/unit/list_instances_columns b/tests/data/unit/list_instances_columns new file mode 100644 index 0000000..70b197d --- /dev/null +++ b/tests/data/unit/list_instances_columns @@ -0,0 +1,4 @@ + SOPInstanceUID Index in series File size +---------------------------------------------- + suid_1 13 139402 + suid_2 13 139402 diff --git a/tests/data/unit/list_instances_columns_no_header b/tests/data/unit/list_instances_columns_no_header new file mode 100644 index 0000000..e768629 --- /dev/null +++ b/tests/data/unit/list_instances_columns_no_header @@ -0,0 +1,2 @@ + suid_1 13 139402 + suid_2 13 139402 diff --git a/tests/data/unit/list_patients_columns b/tests/data/unit/list_patients_columns new file mode 100644 index 0000000..f9ec07f --- /dev/null +++ b/tests/data/unit/list_patients_columns @@ -0,0 +1,4 @@ + PatientID Number of Studies +------------------------------- + foo_id 1 + undefined 2 diff --git a/tests/data/unit/list_patients_columns_no_header b/tests/data/unit/list_patients_columns_no_header new file mode 100644 index 0000000..67cb7f9 --- /dev/null +++ b/tests/data/unit/list_patients_columns_no_header @@ -0,0 +1,2 @@ + foo_id 1 + undefined 2 diff --git a/tests/test.rs b/tests/test.rs index 2769e2e..3d9cabf 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -311,6 +311,18 @@ fn _test_list_patients_no_header() { ); } +#[test] +fn _test_list_patients_columns() { + assert_result( + vec!["patient", "list", "-c", "ID", "PatientName"], + CommandResult::new( + 0, + include_str!("data/patient_list_columns.stdout").to_string(), + "".to_string(), + ), + ); +} + #[test] fn _test_list_patients_error() { assert_result( @@ -347,6 +359,18 @@ fn _test_list_studies_no_header() { ); } +#[test] +fn _test_list_studies_columns() { + assert_result( + vec!["study", "list", "-c", "ID", "AccessionNumber", "StudyDate"], + CommandResult::new( + 0, + include_str!("data/study_list_columns.stdout").to_string(), + "".to_string(), + ), + ); +} + #[test] fn _test_list_studies_error() { assert_result( @@ -383,6 +407,18 @@ fn _test_list_series_no_header() { ); } +#[test] +fn _test_list_series_columns() { + assert_result( + vec!["series", "list", "-c", "ID", "Modality", "BodyPartExamined"], + CommandResult::new( + 0, + include_str!("data/series_list_columns.stdout").to_string(), + "".to_string(), + ), + ); +} + #[test] fn _test_list_series_error() { assert_result( @@ -419,6 +455,18 @@ fn _test_list_instances_no_header() { ); } +#[test] +fn _test_list_instances_columns() { + assert_result( + vec!["instance", "list", "-c", "ID", "InstanceCreationDate"], + CommandResult::new( + 0, + include_str!("data/instance_list_columns.stdout").to_string(), + "".to_string(), + ), + ); +} + #[test] fn _test_list_instances_error() { assert_result( @@ -2245,6 +2293,16 @@ fn test_modalities() { ), ); + // List with columns + assert_result( + vec!["modality", "list", "-c", "Name", "Manufacturer"], + CommandResult::new( + 0, + include_str!("data/modality_list_columns.stdout").to_string(), + "".to_string(), + ), + ); + // Modify assert_result( vec![ @@ -2585,3 +2643,24 @@ fn test_search_instances_no_header() { ), ); } + +#[test] +fn test_search_instances_error() { + assert_result( + vec![ + "instance", + "search", + "-q", + "Modality=PR", + "PregnancyStatus=4", + "-c", + "Foo", + "Bar", + ], + CommandResult::new( + 1, + "".to_string(), + include_str!("data/instances_search_error.stderr").to_string(), + ), + ); +}