<commit_before>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleMenu
{
	/// <summary>
	/// A collection of IMenuItems
	///
	/// Offers various ways to add, retrieve and use items.
	/// </summary>
	public class MenuItemCollection : IEnumerable<CMenuItem>
	{
		private Dictionary<string, CMenuItem> _Menu = new Dictionary<string, CMenuItem> ();
		private CMenuItem _Default = null;

		private StringComparison _StringComparison;

		/// <summary>
		/// Gets or sets how entered commands are compared.
		///
		/// By default, the comparison is case insensitive and culture invariant.
		/// </summary>
		public StringComparison StringComparison
		{
			get
			{
				return _StringComparison;
			}
			set
			{
				_StringComparison = value;
				_Menu = new Dictionary<string, CMenuItem> (_Menu, value.GetCorrespondingComparer ());
			}
		}

		/// <summary>
		/// Create a new, empty MenuItemCollection
		/// </summary>
		public MenuItemCollection ()
		{
			StringComparison = StringComparison.InvariantCultureIgnoreCase;
		}

		/// <summary>
		/// Gets or sets the CMenuItem associated with the specified keyword.
		///
		/// Use the null key to access the default item.
		/// </summary>
		/// <param name="key">
		/// Keyword of the CMenuItem. The selector must match perfectly (i.e. is not an abbreviation of the keyword).
		///
		/// If the key is null, the value refers to the default item.
		/// </param>
		/// <value>
		/// The CMenuItem associated with the specified keyword, or null.
		/// </value>
		/// <returns>
		/// The menu item associated with the specified keyword.
		/// </returns>
		public CMenuItem this[string key]
		{
			get
			{
				if (key == null) {
					return _Default;
				}
				CMenuItem it;
				_Menu.TryGetValue (key, out it);
				return it;
			}
			set
			{
				if (key == null) {
					_Default = value;
				}
				else {
					_Menu[key] = value;
				}
			}
		}

		/// <summary>
		/// Add new command.
		///
		/// The menu's internal structure and abbreviations are updated automatically.
		/// </summary>
		/// <param name="it">Command to add.</param>
		/// <returns>The added CMenuItem</returns>
		public T Add<T> (T it) where T : CMenuItem
		{
			if (it == null) {
				throw new ArgumentNullException ("it");
			}

			if (it.Selector != null) {
				_Menu.Add (it.Selector, it);
			}
			else {
				if (_Default != null) {
					throw new ArgumentException ("The default item was already set.", "it");
				}
				_Default = it;
			}

			return it;
		}

		/// <summary>
		/// Adds a new command from keyword, behavior and help.
		/// </summary>
		/// <param name="selector">Keyword</param>
		/// <param name="execute">Behavior when selected. The behavior provides feedback to the menu.</param>
		/// <param name="help">Descriptive help text</param>
		/// <returns>The added CMenuItem</returns>
		public CMenuItem Add (string selector, Func<string, MenuResult> execute, string help = null)
		{
			var it = new CMenuItem (selector, execute, help);
			Add (it);
			return it;
		}

		/// <summary>
		/// Adds a new command from keyword and help.
		/// </summary>
		/// <param name="selector">Keyword</param>
		/// <returns>The added CMenuItem</returns>
		public CMenuItem Add (string selector, string help = null)
		{
			return Add (selector, (Func<string, MenuResult>) null, help);
		}

		/// <summary>
		/// Creates a new CMenuItem from keyword, behavior and help text.
		/// </summary><commit_msg>menu items have unique parents<commit_after>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleMenu
{
	/// <summary>
	/// A collection of IMenuItems
	///
	/// Offers various ways to add, retrieve and use items.
	/// </summary>
	public class MenuItemCollection : IEnumerable<CMenuItem>
	{
		private Dictionary<string, CMenuItem> _Menu = new Dictionary<string, CMenuItem> ();
		private CMenuItem _Default = null;

		private StringComparison _StringComparison;

		// todo: should be CMenuItem
		public MenuItemCollection Parent { get; private set; }

		/// <summary>
		/// Gets or sets how entered commands are compared.
		///
		/// By default, the comparison is case insensitive and culture invariant.
		/// </summary>
		public StringComparison StringComparison
		{
			get
			{
				return _StringComparison;
			}
			set
			{
				_StringComparison = value;
				_Menu = new Dictionary<string, CMenuItem> (_Menu, value.GetCorrespondingComparer ());
			}
		}

		/// <summary>
		/// Create a new, empty MenuItemCollection
		/// </summary>
		public MenuItemCollection ()
		{
			StringComparison = StringComparison.InvariantCultureIgnoreCase;
		}

		/// <summary>
		/// Gets or sets the CMenuItem associated with the specified keyword.
		///
		/// Use the null key to access the default item.
		/// </summary>
		/// <param name="key">
		/// Keyword of the CMenuItem. The selector must match perfectly (i.e. is not an abbreviation of the keyword).
		///
		/// If the key is null, the value refers to the default item.
		/// </param>
		/// <value>
		/// The CMenuItem associated with the specified keyword, or null.
		/// </value>
		/// <returns>
		/// The menu item associated with the specified keyword.
		/// </returns>
		public CMenuItem this[string key]
		{
			get
			{
				if (key == null) {
					return _Default;
				}
				CMenuItem it;
				_Menu.TryGetValue (key, out it);
				return it;
			}
			set
			{
				if (key == null) {
					_Default = value;
				}
				else {
					_Menu[key] = value;
				}
			}
		}

		/// <summary>
		/// Add new command.
		///
		/// The menu's internal structure and abbreviations are updated automatically.
		/// </summary>
		/// <param name="it">Command to add.</param>
		/// <returns>The added CMenuItem</returns>
		public T Add<T> (T it) where T : CMenuItem
		{
			if (it == null) {
				throw new ArgumentNullException ("it");
			}
			if (it.Parent != null) {
				throw new ArgumentException ("Menuitem already has a parent.", "it");
			}

			if (it.Selector != null) {
				_Menu.Add (it.Selector, it);
			}
			else {
				if (_Default != null) {
					throw new ArgumentException ("The default item was already set.", "it");
				}
				_Default = it;
			}

			it.Parent = this;

			return it;
		}

		/// <summary>
		/// Adds a new command from keyword, behavior and help.
		/// </summary>
		/// <param name="selector">Keyword</param>
		/// <param name="execute">Behavior when selected. The behavior provides feedback to the menu.</param>
		/// <param name="help">Descriptive help text</param>
		/// <returns>The added CMenuItem</returns>
		public CMenuItem Add (string selector, Func<string, MenuResult> execute, string help = null)
		{
			var it = new CMenuItem (selector, execute, help);
			Add (it);
			return it;
		}

		/// <summary>
		/// Adds a new command from keyword and help.
		/// </summary>
		/// <param name="selector">Keyword</param>
		/// <returns>The added CMenuItem</returns>
		public CMenuItem Add (string selector, string help = null)
		{
			return Add (selector, (Func<string, MenuResult>) null, help);
		}

		/// <summary>
		/// Creates a new CMenuItem from keyword, behavior and help text.
		/// </summary>
{'fraction_non_alphanumeric': 0.1361927308174349, 'fraction_numerical': 0.0, 'mean_word_length': 2.6018054162487463, 'pattern_counts': {'":': 0, '<': 93, '<?xml version=': 0, '>': 93, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4108275', 'n_tokens_mistral': 2525, 'n_tokens_neox': 2155, 'n_words': 717}