static func markup_text_edit_selection(text_edit, start_text, end_text):
	if not text_edit.is_selection_active():
		return

	var selection_from_pos = Vector2(text_edit.get_selection_from_column(), text_edit.get_selection_from_line())
	var selection_to_pos = Vector2(text_edit.get_selection_to_column(), text_edit.get_selection_to_line())
	var one_line_selection = selection_from_pos.y == selection_to_pos.y

	text_edit.deselect()
	set_text_edit_cursor_pos(text_edit, selection_from_pos.x, selection_from_pos.y)
	text_edit.insert_text_at_cursor(start_text)

	if one_line_selection:
		selection_to_pos.x += start_text.length()

	set_text_edit_cursor_pos(text_edit, selection_to_pos.x, selection_to_pos.y)
	text_edit.insert_text_at_cursor(end_text)

	if one_line_selection:
		selection_to_pos.x += end_text.length()

	text_edit.select(selection_from_pos.y, selection_from_pos.x, selection_to_pos.y, selection_to_pos.x)

static func get_text_edit_cursor_pos(text_edit):
	return Vector2(text_edit.cursor_get_column(), text_edit.cursor_get_line())

static func set_text_edit_cursor_pos(text_edit, column, line):
	text_edit.cursor_set_column(column)
	text_edit.cursor_set_line(line)

# Position Popup near to its target while within window, solution from ColorPickerButton source code(https://github.com/godotengine/godot/blob/6d8c14f849376905e1577f9fc3f9512bcffb1e3c/scene/gui/color_picker.cpp#L878)
static func popup_on_target(popup, target):
	popup.set_as_minsize()
	var usable_rect = Rect2(Vector2.ZERO, OS.get_real_window_size())
	var cp_rect = Rect2(Vector2.ZERO, popup.get_size())
	for i in 4:
		if i > 1:
			cp_rect.position.y = target.rect_global_position.y - cp_rect.size.y
		else:
			cp_rect.position.y = target.rect_global_position.y + target.get_size().y

		if i & 1:
			cp_rect.position.x = target.rect_global_position.x
		else:
			cp_rect.position.x = target.rect_global_position.x - max(0, cp_rect.size.x - target.get_size().x)

		if usable_rect.encloses(cp_rect):
			break
	popup.set_position(cp_rect.position)
	popup.popup()

# Roughly calculate the display size of option button regarding to the display_text
static func get_option_button_display_size(option_button, display_text):
	# TODO: Improve accuracy
	# Use default theme if not assingned
	var theme = option_button.get_theme() if option_button.get_theme() else Theme.new()
	var string_size = theme.get_font("font", "fonts").get_string_size(display_text)
	var arrow_icon = theme.get_icon("arrow", "styles")
	# Takes arrow icon size into account
	string_size.x += arrow_icon.get_width()
	return string_size
