git.rs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. use nu_ansi_term::{AnsiString as ANSIString, Style};
  2. use crate::fs::fields as f;
  3. use crate::output::cell::{DisplayWidth, TextCell};
  4. impl f::Git {
  5. pub fn render(self, colours: &dyn Colours) -> TextCell {
  6. TextCell {
  7. width: DisplayWidth::from(2),
  8. contents: vec![self.staged.render(colours), self.unstaged.render(colours)].into(),
  9. }
  10. }
  11. }
  12. impl f::GitStatus {
  13. fn render(self, colours: &dyn Colours) -> ANSIString<'static> {
  14. #[rustfmt::skip]
  15. return match self {
  16. Self::NotModified => colours.not_modified().paint("-"),
  17. Self::New => colours.new().paint("N"),
  18. Self::Modified => colours.modified().paint("M"),
  19. Self::Deleted => colours.deleted().paint("D"),
  20. Self::Renamed => colours.renamed().paint("R"),
  21. Self::TypeChange => colours.type_change().paint("T"),
  22. Self::Ignored => colours.ignored().paint("I"),
  23. Self::Conflicted => colours.conflicted().paint("U"),
  24. };
  25. }
  26. }
  27. pub trait Colours {
  28. fn not_modified(&self) -> Style;
  29. // FIXME: this amount of allows needed to keep clippy happy should be enough
  30. // of an argument that new needs to be renamed.
  31. #[allow(clippy::new_ret_no_self, clippy::wrong_self_convention)]
  32. fn new(&self) -> Style;
  33. fn modified(&self) -> Style;
  34. fn deleted(&self) -> Style;
  35. fn renamed(&self) -> Style;
  36. fn type_change(&self) -> Style;
  37. fn ignored(&self) -> Style;
  38. fn conflicted(&self) -> Style;
  39. }
  40. impl f::SubdirGitRepo {
  41. pub fn render(self, colours: &dyn RepoColours) -> TextCell {
  42. let branch_name = match self.branch {
  43. Some(name) => {
  44. if name == "main" || name == "master" {
  45. colours.branch_main().paint(name)
  46. } else {
  47. colours.branch_other().paint(name)
  48. }
  49. }
  50. None => colours.no_repo().paint("-"),
  51. };
  52. if let Some(status) = self.status {
  53. TextCell {
  54. width: DisplayWidth::from(2) + DisplayWidth::from(branch_name.as_str()),
  55. contents: vec![
  56. status.render(colours),
  57. Style::default().paint(" "),
  58. branch_name,
  59. ]
  60. .into(),
  61. }
  62. } else {
  63. TextCell {
  64. width: DisplayWidth::from(branch_name.as_str()),
  65. contents: vec![branch_name].into(),
  66. }
  67. }
  68. }
  69. }
  70. impl f::SubdirGitRepoStatus {
  71. pub fn render(self, colours: &dyn RepoColours) -> ANSIString<'static> {
  72. match self {
  73. Self::NoRepo => colours.no_repo().paint("-"),
  74. Self::GitClean => colours.git_clean().paint("|"),
  75. Self::GitDirty => colours.git_dirty().paint("+"),
  76. }
  77. }
  78. }
  79. pub trait RepoColours {
  80. fn branch_main(&self) -> Style;
  81. fn branch_other(&self) -> Style;
  82. fn no_repo(&self) -> Style;
  83. fn git_clean(&self) -> Style;
  84. fn git_dirty(&self) -> Style;
  85. }
  86. #[cfg(test)]
  87. pub mod test {
  88. use super::Colours;
  89. use crate::fs::fields as f;
  90. use crate::output::cell::{DisplayWidth, TextCell};
  91. use nu_ansi_term::Color::*;
  92. use nu_ansi_term::Style;
  93. struct TestColours;
  94. impl Colours for TestColours {
  95. fn not_modified(&self) -> Style {
  96. Fixed(90).normal()
  97. }
  98. fn new(&self) -> Style {
  99. Fixed(91).normal()
  100. }
  101. fn modified(&self) -> Style {
  102. Fixed(92).normal()
  103. }
  104. fn deleted(&self) -> Style {
  105. Fixed(93).normal()
  106. }
  107. fn renamed(&self) -> Style {
  108. Fixed(94).normal()
  109. }
  110. fn type_change(&self) -> Style {
  111. Fixed(95).normal()
  112. }
  113. fn ignored(&self) -> Style {
  114. Fixed(96).normal()
  115. }
  116. fn conflicted(&self) -> Style {
  117. Fixed(97).normal()
  118. }
  119. }
  120. #[test]
  121. fn git_blank() {
  122. let stati = f::Git {
  123. staged: f::GitStatus::NotModified,
  124. unstaged: f::GitStatus::NotModified,
  125. };
  126. let expected = TextCell {
  127. width: DisplayWidth::from(2),
  128. contents: vec![Fixed(90).paint("-"), Fixed(90).paint("-")].into(),
  129. };
  130. assert_eq!(expected, stati.render(&TestColours));
  131. }
  132. #[test]
  133. fn git_new_changed() {
  134. let stati = f::Git {
  135. staged: f::GitStatus::New,
  136. unstaged: f::GitStatus::Modified,
  137. };
  138. let expected = TextCell {
  139. width: DisplayWidth::from(2),
  140. contents: vec![Fixed(91).paint("N"), Fixed(92).paint("M")].into(),
  141. };
  142. assert_eq!(expected, stati.render(&TestColours));
  143. }
  144. }