<commit_before>-- Copyright 2007-2013 Mitchell mitchell.att.<EMAIL>.<EMAIL>. See LICENSE.

local gui = gui

--[[ This comment is for LuaDoc.
---
-- Utilities for interacting with Textadept's user interface.
-- @field title (string, Write-only)
--   The title of the Textadept window.
-- @field context_menu
--   The editor's context menu, a [`gui.menu()`](#menu).
--   This is a low-level field. You probably want to use the higher-level
--   `_M.textadept.menu.set_contextmenu()`.
-- @field clipboard_text (string, Read-only)
--   The text on the clipboard.
-- @field statusbar_text (string, Write-only)
--   The text displayed by the statusbar.
-- @field docstatusbar_text (string, Write-only)
--   The text displayed by the buffer statusbar.
-- @field maximized (bool)
--   Whether or not the Textadept window is maximized.
module('gui')]]

local theme = package.searchpath(not CURSES and 'light' or 'term',
                                 _USERHOME..'/themes/?.lua;'..
                                 _HOME..'/themes/?.lua')

-- Helper function for printing messages to buffers.
-- @see gui._print
local function _print(buffer_type, ...)
  if buffer._type ~= buffer_type then
    for i, view in ipairs(_VIEWS) do
      if view.buffer._type == buffer_type then gui.goto_view(i) break end
    end
    if view.buffer._type ~= buffer_type then
      view:split()
      for i, buffer in ipairs(_BUFFERS) do
        if buffer._type == buffer_type then view:goto_buffer(i) break end
      end
      if buffer._type ~= buffer_type then
        buffer.new()._type = buffer_type
        events.emit(events.FILE_OPENED)
      end
    end
  end
  local args, n = {...}, select('#', ...)
  for i = 1, n do args[i] = tostring(args[i]) end
  buffer:append_text(table.concat(args, '\t'))
  buffer:append_text('\n')
  buffer:goto_pos(buffer.length)
  buffer:set_save_point()
end
---
-- Helper function for printing messages to buffers.
-- Splits the view and opens a new buffer for printing messages to. If the
-- message buffer is already open in a view, the message is printed to that
-- view. Otherwise the view is split and the message buffer is opened or
-- displayed before being printed to.
-- @param buffer_type String type of message buffer.
-- @param ... Message strings.
-- @usage gui._print(_L['[Message Buffer]'], message)
-- @name _print
function gui._print(buffer_type, ...) pcall(_print, buffer_type, ...) end

---
-- Prints messages to the Textadept message buffer.
-- Opens a new buffer if one has not already been opened for printing messages.
-- @param ... Message strings.
-- @name print
function gui.print(...) gui._print(_L['[Message Buffer]'], ...) end

---
-- Convenience function for `gui.dialog('filteredlist', ...)` with "Ok" and
-- "Cancel" buttons that returns the text or index of the selection depending on
-- the boolean value of *int_return*.
-- *title* is the title of the dialog, *columns* is a list of column names, and
-- *items* is a list of items to show.
-- @param title The title for the filtered list dialog.
-- @param columns A column name or list of column names.
-- @param items An item or list of items.
-- @param int_return Optional flag indicating whether to return the integer
--   index of the selected item in the filtered list or the string selected
--   item. A `true` value is not compatible with the `'--select-multiple'`
--   option. The default value is `false`.
-- @param ... Optional additional parameters to pass to `gui.dialog()`.
-- @return Either a string or integer on success; `nil` otherwise. In strings,
--   multiple items are separated by newlines.
-- @usage gui.filteredlist('Title', 'Foo', {'Bar', 'Baz'})
-- @usage gui.filteredlist('Title', {'Foo', 'Bar'}, {'a', 'b', 'c', 'd'}, false,
--                         '--output-column', '2')
-- @see dialog
-- @name filteredlist
function gui.filteredlist(title, columns, items, int_return, ...)
  local out = gui.dialog('filteredlist',
                         '--title', title,
                         '--button1', _L['_OK'],
                         '--button2', _L['_Cancel'],
                         '--no-newline',
                         int_return and '' or '--string-output',
                         '--columns', columns,
                         '--items', items,
                         ...)
  local patt = int_return and '^(%-?%d+)\n(%d+)$' or '^([^\n]+)\n(.+)$'
  local response, value = out:match(patt)
  if response == (int_return and '1' or _L['_OK']) then
    return not int_return and value or tonumber(value)
  end
end

---
-- Prompts the user to select a buffer to switch to.
-- @name switch_buffer
function gui.switch_buffer()
  local columns, items = {_L['Name'], _L['File']}, {}
  for _, buffer in ipairs(_BUFFERS) do
    local filename = buffer.filename or buffer._type or _L['Untitled']
    local basename = buffer.filename and filename:match('[^/\\]+$') or filename
    items[#items + 1] = (buffer.dirty and '*' or '')..basename
    items[#items + 1] = filename
  end
  local i = gui.filteredlist(_L['Switch Buffers'], columns, items, true,
                             CURSES and {'--width', gui.size[1] - 2} or '--')
  if i then view:goto_buffer(i + 1) end
end

---
-- Goes to the buffer whose filename is *filename* in an existing view,
-- otherwise splitting the current view if *split* is `true` or going to the
-- next or *preferred_view* view instead of staying in the current one.
-- If *sloppy* is `true`, only the last part of *filename* is matched to a
-- buffer's `filename`.
-- @param filename The filename of the buffer to go to.
-- @param split Optional flag indicating whether or not to open the buffer in a
--   split view if there is only one view. The default value is `false`.
-- @param preferred_view Optional view to open the desired buffer in if the
--   buffer is not visible in any other view.
-- @param sloppy Optional flag indicating whether or not to not match *filename*
--   to `buffer.filename` exactly. When `true`, matches *filename* to only the
--   last part of `buffer.filename` This is useful for run and compile commands
--   which output relative filenames and paths instead of full ones and it is
--   likely that the file in question is already open. The default value is
--   `false`.
-- @name goto_file
function gui.goto_file(filename, split, preferred_view, sloppy)
  local patt = '^'..filename..'$'
  if sloppy then
    local i = filename:reverse():find('[/\\]%.%.?') -- ./ or ../
    patt = i and filename:sub(-i + 1, -1)..'$' or filename..'$'
  end
  if #_VIEWS == 1 and split and not (view.buffer.filename or ''):find(patt) then
    view:split()
  else
    local other_view = _VIEWS[preferred_view]
    for i, v in ipairs(_VIEWS) do
      if (v.buffer.filename or ''):find(patt) then gui.goto_view(i) return end
      if not other_view and v ~= view then other_view = i end
    end
    if other_view then gui.goto_view(other_view) end
  end
  for i, buffer in ipairs(_BUFFERS) do
    if (buffer.filename or ''):find(patt) then view:goto_buffer(i) return end
  end
  io.open_file(filename)
end

---
-- Sets the editor theme name to *name* and optionally sets key-value pair
-- argument properties.
-- User themes override Textadept's default themes when they have the same name.
-- If *name* contains slashes, it is assumed to be an absolute path to a theme
-- instead of a theme name.
-- @param name The name or absolute path of a theme to set.
-- @param ... Optional key-value argument pairs for theme properties to set.
--   These override the theme's defaults.
-- @usage gui.set_theme('light', 'font', 'Monospace', 'fontsize', 12)
-- @name set_theme
function gui.set_theme(name, ...)
  if not name then return end
  name = name:find('[/\\]') and name or
         package.searchpath(name, _USERHOME..'/themes/?.lua;'..
                                  _HOME..'/themes/?.lua')
  if not name or not lfs.attributes(name) then return end
  local buffer, props = buffer, {...}
  local current_buffer, current_view = _BUFFERS[buffer], _VIEWS[view]
  for i = 1, #_BUFFERS do
    view:goto_buffer(i)
    dofile(name)
    for j = 1, #props, 2 do buffer.property[props[j]] = props[j + 1] end
  end
  view:goto_buffer(current_buffer)
  for i = 1, #_VIEWS do
    gui.goto_view(i)
    dofile(name)
    for j = 1, #props, 2 do buffer.property[props[j]] = props[j + 1] end
  end
  gui.goto_view(current_view)
  theme = name
end

local events, events_connect = events, events.connect

-- Loads the theme and properties files.
local function load_theme_and_settings()
  dofile(theme)
  dofile(_HOME..'/properties.lua')
  if lfs.attributes(_USERHOME..'/properties.lua') then
    dofile(_USERHOME..'/properties.lua')<commit_msg>Fixed bug with theme loading during `reset()`; core/gui.lua<commit_after>-- Copyright 2007-2013 Mitchell mitchell.att.foicica.com. See LICENSE.

local gui = gui

--[[ This comment is for LuaDoc.
---
-- Utilities for interacting with Textadept's user interface.
-- @field title (string, Write-only)
--   The title of the Textadept window.
-- @field context_menu
--   The editor's context menu, a [`gui.menu()`](#menu).
--   This is a low-level field. You probably want to use the higher-level
--   `_M.textadept.menu.set_contextmenu()`.
-- @field clipboard_text (string, Read-only)
--   The text on the clipboard.
-- @field statusbar_text (string, Write-only)
--   The text displayed by the statusbar.
-- @field docstatusbar_text (string, Write-only)
--   The text displayed by the buffer statusbar.
-- @field maximized (bool)
--   Whether or not the Textadept window is maximized.
module('gui')]]

local theme = package.searchpath(not CURSES and 'light' or 'term',
                                 _USERHOME..'/themes/?.lua;'..
                                 _HOME..'/themes/?.lua')

-- Helper function for printing messages to buffers.
-- @see gui._print
local function _print(buffer_type, ...)
  if buffer._type ~= buffer_type then
    for i, view in ipairs(_VIEWS) do
      if view.buffer._type == buffer_type then gui.goto_view(i) break end
    end
    if view.buffer._type ~= buffer_type then
      view:split()
      for i, buffer in ipairs(_BUFFERS) do
        if buffer._type == buffer_type then view:goto_buffer(i) break end
      end
      if buffer._type ~= buffer_type then
        buffer.new()._type = buffer_type
        events.emit(events.FILE_OPENED)
      end
    end
  end
  local args, n = {...}, select('#', ...)
  for i = 1, n do args[i] = tostring(args[i]) end
  buffer:append_text(table.concat(args, '\t'))
  buffer:append_text('\n')
  buffer:goto_pos(buffer.length)
  buffer:set_save_point()
end
---
-- Helper function for printing messages to buffers.
-- Splits the view and opens a new buffer for printing messages to. If the
-- message buffer is already open in a view, the message is printed to that
-- view. Otherwise the view is split and the message buffer is opened or
-- displayed before being printed to.
-- @param buffer_type String type of message buffer.
-- @param ... Message strings.
-- @usage gui._print(_L['[Message Buffer]'], message)
-- @name _print
function gui._print(buffer_type, ...) pcall(_print, buffer_type, ...) end

---
-- Prints messages to the Textadept message buffer.
-- Opens a new buffer if one has not already been opened for printing messages.
-- @param ... Message strings.
-- @name print
function gui.print(...) gui._print(_L['[Message Buffer]'], ...) end

---
-- Convenience function for `gui.dialog('filteredlist', ...)` with "Ok" and
-- "Cancel" buttons that returns the text or index of the selection depending on
-- the boolean value of *int_return*.
-- *title* is the title of the dialog, *columns* is a list of column names, and
-- *items* is a list of items to show.
-- @param title The title for the filtered list dialog.
-- @param columns A column name or list of column names.
-- @param items An item or list of items.
-- @param int_return Optional flag indicating whether to return the integer
--   index of the selected item in the filtered list or the string selected
--   item. A `true` value is not compatible with the `'--select-multiple'`
--   option. The default value is `false`.
-- @param ... Optional additional parameters to pass to `gui.dialog()`.
-- @return Either a string or integer on success; `nil` otherwise. In strings,
--   multiple items are separated by newlines.
-- @usage gui.filteredlist('Title', 'Foo', {'Bar', 'Baz'})
-- @usage gui.filteredlist('Title', {'Foo', 'Bar'}, {'a', 'b', 'c', 'd'}, false,
--                         '--output-column', '2')
-- @see dialog
-- @name filteredlist
function gui.filteredlist(title, columns, items, int_return, ...)
  local out = gui.dialog('filteredlist',
                         '--title', title,
                         '--button1', _L['_OK'],
                         '--button2', _L['_Cancel'],
                         '--no-newline',
                         int_return and '' or '--string-output',
                         '--columns', columns,
                         '--items', items,
                         ...)
  local patt = int_return and '^(%-?%d+)\n(%d+)$' or '^([^\n]+)\n(.+)$'
  local response, value = out:match(patt)
  if response == (int_return and '1' or _L['_OK']) then
    return not int_return and value or tonumber(value)
  end
end

---
-- Prompts the user to select a buffer to switch to.
-- @name switch_buffer
function gui.switch_buffer()
  local columns, items = {_L['Name'], _L['File']}, {}
  for _, buffer in ipairs(_BUFFERS) do
    local filename = buffer.filename or buffer._type or _L['Untitled']
    local basename = buffer.filename and filename:match('[^/\\]+$') or filename
    items[#items + 1] = (buffer.dirty and '*' or '')..basename
    items[#items + 1] = filename
  end
  local i = gui.filteredlist(_L['Switch Buffers'], columns, items, true,
                             CURSES and {'--width', gui.size[1] - 2} or '--')
  if i then view:goto_buffer(i + 1) end
end

---
-- Goes to the buffer whose filename is *filename* in an existing view,
-- otherwise splitting the current view if *split* is `true` or going to the
-- next or *preferred_view* view instead of staying in the current one.
-- If *sloppy* is `true`, only the last part of *filename* is matched to a
-- buffer's `filename`.
-- @param filename The filename of the buffer to go to.
-- @param split Optional flag indicating whether or not to open the buffer in a
--   split view if there is only one view. The default value is `false`.
-- @param preferred_view Optional view to open the desired buffer in if the
--   buffer is not visible in any other view.
-- @param sloppy Optional flag indicating whether or not to not match *filename*
--   to `buffer.filename` exactly. When `true`, matches *filename* to only the
--   last part of `buffer.filename` This is useful for run and compile commands
--   which output relative filenames and paths instead of full ones and it is
--   likely that the file in question is already open. The default value is
--   `false`.
-- @name goto_file
function gui.goto_file(filename, split, preferred_view, sloppy)
  local patt = '^'..filename..'$'
  if sloppy then
    local i = filename:reverse():find('[/\\]%.%.?') -- ./ or ../
    patt = i and filename:sub(-i + 1, -1)..'$' or filename..'$'
  end
  if #_VIEWS == 1 and split and not (view.buffer.filename or ''):find(patt) then
    view:split()
  else
    local other_view = _VIEWS[preferred_view]
    for i, v in ipairs(_VIEWS) do
      if (v.buffer.filename or ''):find(patt) then gui.goto_view(i) return end
      if not other_view and v ~= view then other_view = i end
    end
    if other_view then gui.goto_view(other_view) end
  end
  for i, buffer in ipairs(_BUFFERS) do
    if (buffer.filename or ''):find(patt) then view:goto_buffer(i) return end
  end
  io.open_file(filename)
end

---
-- Sets the editor theme name to *name* and optionally sets key-value pair
-- argument properties.
-- User themes override Textadept's default themes when they have the same name.
-- If *name* contains slashes, it is assumed to be an absolute path to a theme
-- instead of a theme name.
-- @param name The name or absolute path of a theme to set.
-- @param ... Optional key-value argument pairs for theme properties to set.
--   These override the theme's defaults.
-- @usage gui.set_theme('light', 'font', 'Monospace', 'fontsize', 12)
-- @name set_theme
function gui.set_theme(name, ...)
  if not name then return end
  name = name:find('[/\\]') and name or
         package.searchpath(name, _USERHOME..'/themes/?.lua;'..
                                  _HOME..'/themes/?.lua')
  if not name or not lfs.attributes(name) then return end
  local props = {...}
  local current_buffer, current_view = _BUFFERS[buffer], _VIEWS[view]
  for i = 1, #_BUFFERS do
    view:goto_buffer(i)
    dofile(name)
    for j = 1, #props, 2 do buffer.property[props[j]] = props[j + 1] end
  end
  view:goto_buffer(current_buffer)
  for i = 1, #_VIEWS do
    gui.goto_view(i)
    dofile(name)
    for j = 1, #props, 2 do buffer.property[props[j]] = props[j + 1] end
  end
  gui.goto_view(current_view)
  theme = name
end

local events, events_connect = events, events.connect

-- Loads the theme and properties files.
local function load_theme_and_settings()
  dofile(theme)
  dofile(_HOME..'/properties.lua')
  if lfs.attributes(_USERHOME..'/properties.lua') then
    dofile(_USERHOME..'/properties.lua')
{'fraction_non_alphanumeric': 0.13117106773823192, 'fraction_numerical': 0.003559127439724455, 'mean_word_length': 2.8203947368421054, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1295560', 'n_tokens_mistral': 5383, 'n_tokens_neox': 5225, 'n_words': 2008}