ui.rs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. //
  2. // imag - the personal information management suite for the commandline
  3. // Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
  4. //
  5. // This library is free software; you can redistribute it and/or
  6. // modify it under the terms of the GNU Lesser General Public
  7. // License as published by the Free Software Foundation; version
  8. // 2.1 of the License.
  9. //
  10. // This library is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. // Lesser General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU Lesser General Public
  16. // License along with this library; if not, write to the Free Software
  17. // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  18. //
  19. use clap::{Arg, ArgMatches, App, SubCommand};
  20. use tag::Tag;
  21. use libimagutil::cli_validators::is_tag;
  22. /// Generates a `clap::SubCommand` to be integrated in the commandline-ui builder for building a
  23. /// "tags --add foo --remove bar" subcommand to do tagging action.
  24. pub fn tag_subcommand<'a, 'b>() -> App<'a, 'b> {
  25. SubCommand::with_name(tag_subcommand_name())
  26. .author("Matthias Beyer <mail@beyermatthias.de>")
  27. .version("0.1")
  28. .about("Add or remove tags")
  29. .arg(tag_add_arg())
  30. .arg(tag_remove_arg())
  31. }
  32. pub fn tag_add_arg<'a, 'b>() -> Arg<'a, 'b> {
  33. Arg::with_name(tag_subcommand_add_arg_name())
  34. .short("a")
  35. .long("add")
  36. .takes_value(true)
  37. .value_name("tags")
  38. .multiple(true)
  39. .validator(is_tag)
  40. .help("Add tags, seperated by comma or by specifying multiple times")
  41. }
  42. pub fn tag_remove_arg<'a, 'b>() -> Arg<'a, 'b> {
  43. Arg::with_name(tag_subcommand_remove_arg_name())
  44. .short("r")
  45. .long("remove")
  46. .takes_value(true)
  47. .value_name("tags")
  48. .multiple(true)
  49. .validator(is_tag)
  50. .help("Remove tags, seperated by comma or by specifying multiple times")
  51. }
  52. pub fn tag_subcommand_name() -> &'static str {
  53. "tags"
  54. }
  55. pub fn tag_subcommand_add_arg_name() -> &'static str {
  56. "add-tags"
  57. }
  58. pub fn tag_subcommand_remove_arg_name() -> &'static str {
  59. "remove-tags"
  60. }
  61. pub fn tag_subcommand_names() -> Vec<&'static str> {
  62. vec![tag_subcommand_add_arg_name(), tag_subcommand_remove_arg_name()]
  63. }
  64. /// Generates a `clap::Arg` which can be integrated into the commandline-ui builder for building a
  65. /// "-t" or "--tags" argument which takes values for tagging actions (add, remove)
  66. pub fn tag_argument<'a, 'b>() -> Arg<'a, 'b> {
  67. Arg::with_name(tag_argument_name())
  68. .short("t")
  69. .long("tags")
  70. .takes_value(true)
  71. .multiple(true)
  72. .validator(is_tag)
  73. .help("Add or remove tags, prefixed by '+' (for adding) or '-' (for removing)")
  74. }
  75. pub fn tag_argument_name() -> &'static str {
  76. "specify-tags"
  77. }
  78. /// Get the tags which should be added from the commandline
  79. ///
  80. /// Returns none if the argument was not specified
  81. pub fn get_add_tags(matches: &ArgMatches) -> Option<Vec<Tag>> {
  82. let add = tag_subcommand_add_arg_name();
  83. extract_tags(matches, add, '+')
  84. .or_else(|| matches.values_of(add).map(|values| values.map(String::from).collect()))
  85. }
  86. /// Get the tags which should be removed from the commandline
  87. ///
  88. /// Returns none if the argument was not specified
  89. pub fn get_remove_tags(matches: &ArgMatches) -> Option<Vec<Tag>> {
  90. let rem = tag_subcommand_remove_arg_name();
  91. extract_tags(matches, rem, '+')
  92. .or_else(|| matches.values_of(rem).map(|values| values.map(String::from).collect()))
  93. }
  94. fn extract_tags(matches: &ArgMatches, specifier: &str, specchar: char) -> Option<Vec<Tag>> {
  95. if let Some(submatch) = matches.subcommand_matches("tags") {
  96. submatch.values_of(specifier)
  97. .map(|values| values.map(String::from).collect())
  98. } else {
  99. matches.values_of("specify-tags")
  100. .map(|argmatches| {
  101. argmatches
  102. .map(String::from)
  103. .filter(|s| s.starts_with(specchar))
  104. .map(|s| {
  105. String::from(s.split_at(1).1)
  106. })
  107. .collect()
  108. })
  109. }
  110. }