<commit_before>/* globals $, window, document, FileReader, chrome, localStorage, alert */

/*
initialize the main page
- handle button clicks (import/export/hotkey stuff)
- handle clipboard paste
- handle errors
- load document from localStorage/chrome storage (fall back to plain in-memory datastructures)
- initialize objects (session, settings, etc.) with relevant divs
*/

import * as constants from './constants';
import * as errors from './errors';
import * as utils from './utils';
import * as Logger from './logger';

import * as Modes from './modes';
import KeyEmitter from './keyEmitter';
import { KeyStream } from './keyHandler';
import KeyHandler from './keyHandler';
import * as DataStore from './datastore';
import Document from './document';
import Settings from './settings';
import { PluginsManager } from './plugins';
import Path from './path';
import Session from './session';
import * as Render from './render';

import keyDefinitions from './keyDefinitions';
// load all definitions
require('./definitions/*.js', {mode: 'expand'});
// load all plugins
require('../../plugins/**/*.js', {mode: 'expand'});
import KeyBindings from './keyBindings';


let $keybindingsDiv = $('#keybindings');
let $settingsDiv = $('#settings');
let $modeDiv = $('#mode');

let docname = window.location.pathname.split('/')[1];

let changeStyle = theme => $('body').attr('id', theme);

let create_session = async function(doc, to_load) {

  //###################
  // Settings
  //###################

  let settings = new Settings(doc.store, {mainDiv: $settingsDiv});

  let theme = await settings.getSetting('theme');
  changeStyle(theme);
  $settingsDiv.find('.theme-selection').val(theme);
  $settingsDiv.find('.theme-selection').on('input', function(/*e*/) {
    let theme = this.value;
    settings.setSetting('theme', theme);
    return changeStyle(theme);
  });

  let showingKeyBindings = await settings.getSetting('showKeyBindings');
  $keybindingsDiv.toggleClass('active', showingKeyBindings);

  //###################
  // hotkeys and key bindings
  //###################

  let hotkey_settings = await settings.getSetting('hotkeys', {});
  let key_bindings = new KeyBindings(keyDefinitions, hotkey_settings);

  //###################
  // session
  //###################

  if (!doc.hasChildren(doc.root.row)) {
    // HACKY: should load the actual data now, but since plugins aren't enabled...
    doc.load(constants.empty_data);
  }

  const viewRoot = Path.loadFromAncestry(doc.store.getLastViewRoot());

  // TODO: if we ever support multi-user case, ensure last view root is valid
  let cursorPath;
  if (viewRoot.isRoot()) {
    cursorPath = doc.getChildren(viewRoot)[0];
  } else {
    cursorPath = viewRoot;
  }

  let session = new Session(doc, {
    bindings: key_bindings,
    settings,
    mainDiv: $('#view'),
    messageDiv: $('#message'),
    menuDiv: $('#menu'),
    viewRoot: viewRoot,
    cursorPath: cursorPath,
  });

  key_bindings.on('applied_hotkey_settings', function(hotkey_settings) {
    settings.setSetting('hotkeys', hotkey_settings);
    Render.renderHotkeysTable(key_bindings);
    return Render.renderModeTable(key_bindings, session.mode, $keybindingsDiv);
  });

  let render_mode_info = function(mode) {
    Render.renderModeTable(key_bindings, mode, $keybindingsDiv);
    return $modeDiv.text(Modes.getMode(mode).name);
  };

  render_mode_info(session.mode);
  session.on('modeChange', (oldmode, newmode) => render_mode_info(newmode)
  );

  session.on('toggleBindingsDiv', function() {
    $keybindingsDiv.toggleClass('active');
    doc.store.setSetting('showKeyBindings', $keybindingsDiv.hasClass('active'));
    return Render.renderModeTable(key_bindings, session.mode, $keybindingsDiv);
  });

  //###################
  // plugins
  //###################

  let pluginManager = new PluginsManager(session, $('#plugins'));
  let enabledPlugins = (await settings.getSetting('enabledPlugins')) || ['Marks'];
  enabledPlugins.forEach((plugin_name) => pluginManager.enable(plugin_name));
  Render.renderPlugins(pluginManager);

  pluginManager.on('status', () => Render.renderPlugins(pluginManager));

  pluginManager.on('enabledPluginsChange', function(enabled) {
    settings.setSetting('enabledPlugins', enabled);
    Render.renderPlugins(pluginManager);
    Render.renderSession(session);
    // refresh hotkeys, if any new ones were added/removed
    Render.renderHotkeysTable(session.bindings);
    return Render.renderModeTable(session.bindings, session.mode, $keybindingsDiv);
  });

  //###################
  // load data
  //###################

  if (to_load !== null) {
    doc.load(to_load);
    // a bit hack.  without this, you can undo initial marks, for example
    session.reset_history();
    session.reset_jump_history();
  }

  //###################
  // prepare dom
  //###################

  // render when ready
  $(document).ready(function() {
    if (docname !== '') { document.title = `${docname} - Vimflowy`; }
    return Render.renderSession(session);
  });

  let key_handler = new KeyHandler(session, key_bindings);

  let key_emitter = new KeyEmitter();
  key_emitter.listen();
  key_emitter.on('keydown', (key) => {
    // TODO HACKY: this is just a best guess... e.g. the mode could be wrong
    // problem is that we process asynchronously, but need to
    // return synchronously
    const keyStream = new KeyStream([key]);

    let handled = true;
    // ALSO HACKY: getCommand currently causes key_transforms in search mode
    if ((session.mode === Modes.modes.NORMAL) || (session.mode === Modes.modes.INSERT)) {
      handled = key_handler.getCommand(session.mode, keyStream).handled;
    }
    // fire and forget
    key_handler.handleKey(key).then(() => {
      Render.renderSession(session);
    });
    return handled;
  });

  session.on('importFinished', () => Render.renderSession(session));

  // expose globals, for debugging
  window.Modes = Modes;
  window.session = session;
  window.key_handler = key_handler;<commit_msg>fix terrible bug<commit_after>/* globals $, window, document, FileReader, chrome, localStorage, alert */

/*
initialize the main page
- handle button clicks (import/export/hotkey stuff)
- handle clipboard paste
- handle errors
- load document from localStorage/chrome storage (fall back to plain in-memory datastructures)
- initialize objects (session, settings, etc.) with relevant divs
*/

import * as constants from './constants';
import * as errors from './errors';
import * as utils from './utils';
import * as Logger from './logger';

import * as Modes from './modes';
import KeyEmitter from './keyEmitter';
import { KeyStream } from './keyHandler';
import KeyHandler from './keyHandler';
import * as DataStore from './datastore';
import Document from './document';
import Settings from './settings';
import { PluginsManager } from './plugins';
import Path from './path';
import Session from './session';
import * as Render from './render';

import keyDefinitions from './keyDefinitions';
// load all definitions
require('./definitions/*.js', {mode: 'expand'});
// load all plugins
require('../../plugins/**/*.js', {mode: 'expand'});
import KeyBindings from './keyBindings';


let $keybindingsDiv = $('#keybindings');
let $settingsDiv = $('#settings');
let $modeDiv = $('#mode');

let docname = window.location.pathname.split('/')[1];

let changeStyle = theme => $('body').attr('id', theme);

let create_session = async function(doc, to_load) {

  //###################
  // Settings
  //###################

  let settings = new Settings(doc.store, {mainDiv: $settingsDiv});

  let theme = await settings.getSetting('theme');
  changeStyle(theme);
  $settingsDiv.find('.theme-selection').val(theme);
  $settingsDiv.find('.theme-selection').on('input', function(/*e*/) {
    let theme = this.value;
    settings.setSetting('theme', theme);
    return changeStyle(theme);
  });

  let showingKeyBindings = await settings.getSetting('showKeyBindings');
  $keybindingsDiv.toggleClass('active', showingKeyBindings);

  //###################
  // hotkeys and key bindings
  //###################

  let hotkey_settings = await settings.getSetting('hotkeys', {});
  let key_bindings = new KeyBindings(keyDefinitions, hotkey_settings);

  //###################
  // session
  //###################

  if (!doc.hasChildren(doc.root.row)) {
    // HACKY: should load the actual data now, but since plugins aren't enabled...
    doc.load(constants.empty_data);
  }

  const viewRoot = Path.loadFromAncestry(doc.store.getLastViewRoot());

  // TODO: if we ever support multi-user case, ensure last view root is valid
  let cursorPath;
  if (viewRoot.isRoot()) {
    cursorPath = doc.getChildren(viewRoot)[0];
  } else {
    cursorPath = viewRoot;
  }

  let session = new Session(doc, {
    bindings: key_bindings,
    settings,
    mainDiv: $('#view'),
    messageDiv: $('#message'),
    menuDiv: $('#menu'),
    viewRoot: viewRoot,
    cursorPath: cursorPath,
  });

  key_bindings.on('applied_hotkey_settings', function(hotkey_settings) {
    settings.setSetting('hotkeys', hotkey_settings);
    Render.renderHotkeysTable(key_bindings);
    return Render.renderModeTable(key_bindings, session.mode, $keybindingsDiv);
  });

  let render_mode_info = function(mode) {
    Render.renderModeTable(key_bindings, mode, $keybindingsDiv);
    return $modeDiv.text(Modes.getMode(mode).name);
  };

  render_mode_info(session.mode);
  session.on('modeChange', (oldmode, newmode) => render_mode_info(newmode)
  );

  session.on('toggleBindingsDiv', function() {
    $keybindingsDiv.toggleClass('active');
    doc.store.setSetting('showKeyBindings', $keybindingsDiv.hasClass('active'));
    return Render.renderModeTable(key_bindings, session.mode, $keybindingsDiv);
  });

  //###################
  // plugins
  //###################

  let pluginManager = new PluginsManager(session, $('#plugins'));
  let enabledPlugins = (await settings.getSetting('enabledPlugins')) || ['Marks'];
  enabledPlugins.forEach((plugin_name) => pluginManager.enable(plugin_name));
  Render.renderPlugins(pluginManager);

  pluginManager.on('status', () => Render.renderPlugins(pluginManager));

  pluginManager.on('enabledPluginsChange', function(enabled) {
    settings.setSetting('enabledPlugins', enabled);
    Render.renderPlugins(pluginManager);
    Render.renderSession(session);
    // refresh hotkeys, if any new ones were added/removed
    Render.renderHotkeysTable(session.bindings);
    return Render.renderModeTable(session.bindings, session.mode, $keybindingsDiv);
  });

  //###################
  // load data
  //###################

  if (to_load !== null) {
    doc.load(to_load);
    // a bit hack.  without this, you can undo initial marks, for example
    session.reset_history();
    session.reset_jump_history();
  }

  //###################
  // prepare dom
  //###################

  // render when ready
  $(document).ready(function() {
    if (docname !== '') { document.title = `${docname} - Vimflowy`; }
    return Render.renderSession(session);
  });

  let key_handler = new KeyHandler(session, key_bindings);

  let key_emitter = new KeyEmitter();
  key_emitter.listen();
  key_emitter.on('keydown', (key) => {
    // TODO HACKY: this is just a best guess... e.g. the mode could be wrong
    // problem is that we process asynchronously, but need to
    // return synchronously
    const keyStream = new KeyStream([key]);

    let handled = true;
    // ALSO HACKY: getCommand currently causes key_transforms in search mode
    if (session.mode === Modes.modes.NORMAL) {
      handled = key_handler.getCommand(session.mode, keyStream).handled;
    }
    // fire and forget
    key_handler.handleKey(key).then(() => {
      Render.renderSession(session);
    });
    return handled;
  });

  session.on('importFinished', () => Render.renderSession(session));

  // expose globals, for debugging
  window.Modes = Modes;
  window.session = session;
  window.key_handler = key_handler;
{'fraction_non_alphanumeric': 0.17966666666666667, 'fraction_numerical': 0.0003333333333333333, 'mean_word_length': 4.213292788879236, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 17, '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': '2711750', 'n_tokens_mistral': 3547, 'n_tokens_neox': 3482, 'n_words': 855}