Repository: gitui-org/gitui (language: rust)

Issue:
creating annotated tag broke
this is how creating annotated tags used to work (before `0.25`):

![tag-annotation](https://github.com/extrawurst/gitui/assets/776816/08d45223-6a7b-4ab6-9ffc-f031064ff02a)

now its broken. i suspect this broke during the transition to textarea in b9a2e13 by @pm100 
creating annotated tag broke
this is how creating annotated tags used to work (before `0.25`):

![tag-annotation](https://github.com/extrawurst/gitui/assets/776816/08d45223-6a7b-4ab6-9ffc-f031064ff02a)

now its broken. i suspect this broke during the transition to textarea in b9a2e13 by @pm100 


Discussion / hints:
to be clear 
- 't' should be a single line terminated by 'return/enter'?
- 'T' should be multi line (like commit). With Enter creating a new line and ctrl-enter being confirm and close?



@michaelAug is on this one
The issue is with `TextInputComponent` handling the ctrl-a keypress to move the cursor to the beginning of line.
https://github.com/extrawurst/gitui/blob/0ab1ff862592d5a16785306d64c035db24e87380/src/components/textinput.rs#L421-L435

So there's multiple ways to handle this. We could make `TextInputComponent` not handle ctrl-a keybind since there are multiple shortcuts for moving the cursor to head. Or we could change the annotation keybind to something else. Which option would you prefer @extrawurst ?
I would do what I did with all other 'known' keystrokes that map to things that are not hugely important to tuit xtarea.  Filter them out at the start, you will see a set of skipped keystrokes at the start of the key handling (on the road so I can't point to the specific line)
Thanks @pm100, I think your filtering out code was removed in https://github.com/extrawurst/gitui/pull/2053 though...
to be clear 
- 't' should be a single line terminated by 'return/enter'?
- 'T' should be multi line (like commit). With Enter creating a new line and ctrl-enter being confirm and close?



@michaelAug is on this one
The issue is with `TextInputComponent` handling the ctrl-a keypress to move the cursor to the beginning of line.
https://github.com/extrawurst/gitui/blob/0ab1ff862592d5a16785306d64c035db24e87380/src/components/textinput.rs#L421-L435

So there's multiple ways to handle this. We could make `TextInputComponent` not handle ctrl-a keybind since there are multiple shortcuts for moving the cursor to head. Or we could change the annotation keybind to something else. Which option would you prefer @extrawurst ?
I would do what I did with all other 'known' keystrokes that map to things that are not hugely important to tuit xtarea.  Filter them out at the start, you will see a set of skipped keystrokes at the start of the key handling (on the road so I can't point to the specific line)
Thanks @pm100, I think your filtering out code was removed in https://github.com/extrawurst/gitui/pull/2053 though...

Fix patch:
diff --git a/src/components/textinput.rs b/src/components/textinput.rs
index 0dff6e53c4..df87ae9d2c 100644
--- a/src/components/textinput.rs
+++ b/src/components/textinput.rs
@@ -88,6 +88,12 @@ impl TextInputComponent {
 		self
 	}
 
+	///
+	pub fn set_input_type(&mut self, input_type: InputType) {
+		self.clear();
+		self.input_type = input_type;
+	}
+
 	/// Clear the `msg`.
 	pub fn clear(&mut self) {
 		self.msg.take();
diff --git a/src/popups/tag_commit.rs b/src/popups/tag_commit.rs
index 4f52274762..696aba171c 100644
--- a/src/popups/tag_commit.rs
+++ b/src/popups/tag_commit.rs
@@ -46,9 +46,13 @@ impl Component for TagCommitPopup {
 		if self.is_visible() || force_all {
 			self.input.commands(out, force_all);
 
+			let is_annotation_mode =
+				matches!(self.mode, Mode::Annotation { .. });
+
 			out.push(CommandInfo::new(
 				strings::commands::tag_commit_confirm_msg(
 					&self.key_config,
+					is_annotation_mode,
 				),
 				self.is_valid_tag(),
 				true,
@@ -66,37 +70,34 @@ impl Component for TagCommitPopup {
 
 	fn event(&mut self, ev: &Event) -> Result<EventState> {
 		if self.is_visible() {
-			if self.input.event(ev)?.is_consumed() {
-				return Ok(EventState::Consumed);
-			}
-
 			if let Event::Key(e) = ev {
-				if key_match(e, self.key_config.keys.enter)
+				let is_annotation_mode =
+					matches!(self.mode, Mode::Annotation { .. });
+
+				if !is_annotation_mode
+					&& key_match(e, self.key_config.keys.enter)
 					&& self.is_valid_tag()
 				{
 					try_or_popup!(self, "tag error:", self.tag());
+					return Ok(EventState::Consumed);
+				}
+				if is_annotation_mode
+					&& key_match(e, self.key_config.keys.commit)
+				{
+					try_or_popup!(self, "tag error:", self.tag());
+					return Ok(EventState::Consumed);
 				} else if key_match(
 					e,
 					self.key_config.keys.tag_annotate,
 				) && self.is_valid_tag()
 				{
-					let tag_name: String =
-						self.input.get_text().into();
-
-					self.input.clear();
-					self.input.set_title(
-						strings::tag_popup_annotation_title(
-							&tag_name,
-						),
-					);
-					self.input.set_default_msg(
-						strings::tag_popup_annotation_msg(),
-					);
-					self.mode = Mode::Annotation { tag_name };
+					self.start_annotate_mode();
+					return Ok(EventState::Consumed);
 				}
-
-				return Ok(EventState::Consumed);
 			}
+
+			self.input.event(ev)?;
+			return Ok(EventState::Consumed);
 		}
 		Ok(EventState::NotConsumed)
 	}
@@ -111,6 +112,7 @@ impl Component for TagCommitPopup {
 
 	fn show(&mut self) -> Result<()> {
 		self.mode = Mode::Name;
+		self.input.set_input_type(InputType::Singleline);
 		self.input.set_title(strings::tag_popup_name_title());
 		self.input.set_default_msg(strings::tag_popup_name_msg());
 		self.input.show()?;
@@ -166,6 +168,7 @@ impl TagCommitPopup {
 				.flatten()
 				.and_then(|val| val.parse::<bool>().ok())
 				.unwrap_or_default();
+
 		anyhow::ensure!(!gpgsign, "config tag.gpgsign=true detected.\ngpg signing not supported.\ndeactivate in your repo/gitconfig to be able to tag without signing.");
 
 		let (tag_name, tag_annotation) = self.tag_info();
@@ -201,4 +204,17 @@ impl TagCommitPopup {
 
 		Ok(())
 	}
+
+	fn start_annotate_mode(&mut self) {
+		let tag_name: String = self.input.get_text().into();
+
+		self.input.clear();
+		self.input.set_input_type(InputType::Multiline);
+		self.input.set_title(strings::tag_popup_annotation_title(
+			&tag_name,
+		));
+		self.input
+			.set_default_msg(strings::tag_popup_annotation_msg());
+		self.mode = Mode::Annotation { tag_name };
+	}
 }
diff --git a/src/strings.rs b/src/strings.rs
index a369a8692e..67eb79ba7a 100644
--- a/src/strings.rs
+++ b/src/strings.rs
@@ -1423,11 +1423,16 @@ pub mod commands {
 	}
 	pub fn tag_commit_confirm_msg(
 		key_config: &SharedKeyConfig,
+		is_annotation_mode: bool,
 	) -> CommandText {
 		CommandText::new(
 			format!(
 				"Tag [{}]",
-				key_config.get_hint(key_config.keys.enter),
+				key_config.get_hint(if is_annotation_mode {
+					key_config.keys.commit
+				} else {
+					key_config.keys.enter
+				}),
 			),
 			"tag commit",
 			CMD_GROUP_LOG,


Test patch: