public LanguageCompilerSpecPair askLanguage(String title, String approveButtonText)
			throws CancelledException {

		String key = join(title, approveButtonText);
		LanguageCompilerSpecPair existingValue =
			loadAskValue(this::parseLanguageCompileSpecPair, key);
		if (isRunningHeadless()) {
			return existingValue;
		}

		Class<LanguageCompilerSpecPair> clazz = LanguageCompilerSpecPair.class;
		LanguageCompilerSpecPair choice =
			doAsk(clazz, title, approveButtonText, existingValue, lastValue -> {

				SelectLanguageDialog dialog = new SelectLanguageDialog(title, approveButtonText);
				dialog.setSelectedLanguage(lastValue);
				dialog.show();
				if (dialog.wasCancelled()) {
					throw new CancelledException();
				}

				return dialog.getSelectedLanguage();
			});

		return choice;
	}
Returns a LanguageCompilerSpecPair, using the String parameters for guidance. The actual
behavior of the method depends on your environment, which can be GUI or headless.
<p>
Regardless of environment -- if script arguments have been set, this method will use the
next argument in the array and advance the array index so the next call to an ask method
will get the next argument.  If there are no script arguments and a .properties file
sharing the same base name as the Ghidra Script exists (i.e., Script1.properties for
Script1.java), then this method will then look there for the String value to return.
The method will look in the .properties file by searching for a property name that is a
space-separated concatenation of the input String parameters (title + " " + message).
If that property name exists and its value represents a valid LanguageCompilerSpecPair value,
then the .properties value will be used in the following way:
<ol>
		<li>In the GUI environment, this method displays a language table dialog and returns
			the selected language. If the same popup has been run before in the same session,
			the last-used language will be pre-selected. If not, the language specified in the
			.properties file will be pre-selected (if it exists).</li>
		<li>In the headless environment, this method returns a LanguageCompilerSpecPair
			representing the .properties value (if it exists), or throws an Exception if there
			is an invalid or missing .properties value.</li>
</ol>
@param title the title of the dialog (in GUI mode) or the first part of the variable name
			(in headless mode or when using .properties file)
@param approveButtonText the approve button text (in GUI mode - typically, this would be
			"Open" or "Save") or the second part of the variable name (in headless mode or
			when using .properties file)
@return the selected LanguageCompilerSpecPair
@throws CancelledException if the user hit the 'cancel' button
@throws IllegalArgumentException if in headless mode, there was a missing or invalid	language
			specified in the .properties file
Ghidra/Features/Base/src/main/java/ghidra/app/script/GhidraScript.java