<commit_before>'use babel';
import fs from 'fs';
import path from 'path';
import SubAtom from 'sub-atom';
import $ from 'jquery';

// css classes on the status items that we don't want
// to be serialized
const genericCSSClasses = /inline-block/i

const configPath = path.join(path.dirname(atom.config.getUserConfigPath()), 'move-status-items.json');

var disposables;

export function activate() {
  disposables = new SubAtom();
  atom.packages.onDidActivateInitialPackages(function() {
    setInitialOrder();
    handleEvents();
  });
}

export function deactivate() {
  disposables.dispose();
  [disposables, serializedState] = [];
}

function handleEvents() {
  disposables.add('status-bar [class*="status-bar-"]', 'mousedown', '> *', dragStart);
}

var dragDisposable;

function dragStart(event) {
  var currentItem = event.currentTarget;
  dragDisposable = new SubAtom();
  dragDisposable.add(document.body, 'mousemove', (event) => drag(currentItem, event));
  dragDisposable.add(document.body, 'mouseup mouseleave', dragEnd);
}

function drag(currentItem, event) {
  var {pageX} = event;
  var nextItem = getNextItem(currentItem);
  var previousItem = getNextItem(currentItem, true);
  if(previousItem && pageX < $(previousItem).offset().left + previousItem.clientWidth / 2) {
    $(currentItem).insertBefore(previousItem);
  } else if(nextItem && pageX > $(nextItem).offset().left + nextItem.clientWidth / 2) {
    $(currentItem).insertAfter(nextItem);
  }
}

function dragEnd(event) {
  dragDisposable.dispose();
  dragDisposable = null;
  saveOrder();
}

function getNextItem(currentItem, reverse = false) {
  var parent = currentItem.parentNode;
  var currentIndex = Array.prototype.indexOf.call(parent.children, currentItem);
  while(currentIndex > 0 && currentIndex < parent.children.length - 1) {
    currentIndex += Math.pow(-1, reverse);
    let item = parent.children[currentIndex];
    if(isVisible(item)) return item;
  }
}

function isVisible(element) {
  var {display, visibility, width} = window.getComputedStyle(element);
  width = width ? parseInt(width) : element.clientWidth;
  return display != 'none' && visibility != 'hidden' && width > 0;
}

function saveOrder() {
  var serializedState = {};
  for(let side of ['left', 'right']) {
    serializedState[side] = [];
    let statusItems = document.querySelectorAll(`status-bar .status-bar-${side} > *`);
    for(let i in statusItems) {
      if(statusItems[i] instanceof HTMLElement) serializedState[side].push(serializeStatusItem(statusItems[i]));
    }
  }
  fs.writeFileSync(configPath, JSON.stringify(serializedState));
  return serializedState;
}

function serializeStatusItem(statusItem) {
  var serializedStatusItem = statusItem.tagName.toLowerCase();
  if(statusItem.className) {
    for(let className of statusItem.className.split(' ')) {
      if(className.match(/inline-block/)) continue;
      serializedStatusItem += `.${className}`;
    }
  }
  var isAttr = statusItem.getAttribute('is');
  if(isAttr) serializedStatusItem += `[is="${isAttr}"]`;
  return serializedStatusItem;
}

function setInitialOrder() {
  fs.readFile(configPath, 'utf8', function(err, serializedState) {
    serializedState = JSON.parse(serializedState);<commit_msg>fix issue when ~/.atom/move-status-items.json didn't exist<commit_after>'use babel';
import fs from 'fs';
import path from 'path';
import SubAtom from 'sub-atom';
import $ from 'jquery';

// css classes on the status items that we don't want
// to be serialized
const genericCSSClasses = /inline-block/i

const configPath = path.join(path.dirname(atom.config.getUserConfigPath()), 'move-status-items.json');

if(!fs.existsSync(configPath)) fs.writeFileSync(configPath, '{}');

var disposables;

export function activate() {
  disposables = new SubAtom();
  atom.packages.onDidActivateInitialPackages(function() {
    setInitialOrder();
    handleEvents();
  });
}

export function deactivate() {
  disposables.dispose();
  [disposables, serializedState] = [];
}

function handleEvents() {
  disposables.add('status-bar [class*="status-bar-"]', 'mousedown', '> *', dragStart);
}

var dragDisposable;

function dragStart(event) {
  var currentItem = event.currentTarget;
  dragDisposable = new SubAtom();
  dragDisposable.add(document.body, 'mousemove', (event) => drag(currentItem, event));
  dragDisposable.add(document.body, 'mouseup mouseleave', dragEnd);
}

function drag(currentItem, event) {
  var {pageX} = event;
  var nextItem = getNextItem(currentItem);
  var previousItem = getNextItem(currentItem, true);
  if(previousItem && pageX < $(previousItem).offset().left + previousItem.clientWidth / 2) {
    $(currentItem).insertBefore(previousItem);
  } else if(nextItem && pageX > $(nextItem).offset().left + nextItem.clientWidth / 2) {
    $(currentItem).insertAfter(nextItem);
  }
}

function dragEnd(event) {
  dragDisposable.dispose();
  dragDisposable = null;
  saveOrder();
}

function getNextItem(currentItem, reverse = false) {
  var parent = currentItem.parentNode;
  var currentIndex = Array.prototype.indexOf.call(parent.children, currentItem);
  while(currentIndex > 0 && currentIndex < parent.children.length - 1) {
    currentIndex += Math.pow(-1, reverse);
    let item = parent.children[currentIndex];
    if(isVisible(item)) return item;
  }
}

function isVisible(element) {
  var {display, visibility, width} = window.getComputedStyle(element);
  width = width ? parseInt(width) : element.clientWidth;
  return display != 'none' && visibility != 'hidden' && width > 0;
}

function saveOrder() {
  var serializedState = {};
  for(let side of ['left', 'right']) {
    serializedState[side] = [];
    let statusItems = document.querySelectorAll(`status-bar .status-bar-${side} > *`);
    for(let i in statusItems) {
      if(statusItems[i] instanceof HTMLElement) serializedState[side].push(serializeStatusItem(statusItems[i]));
    }
  }
  fs.writeFileSync(configPath, JSON.stringify(serializedState));
  return serializedState;
}

function serializeStatusItem(statusItem) {
  var serializedStatusItem = statusItem.tagName.toLowerCase();
  if(statusItem.className) {
    for(let className of statusItem.className.split(' ')) {
      if(className.match(/inline-block/)) continue;
      serializedStatusItem += `.${className}`;
    }
  }
  var isAttr = statusItem.getAttribute('is');
  if(isAttr) serializedStatusItem += `[is="${isAttr}"]`;
  return serializedStatusItem;
}

function setInitialOrder() {
  fs.readFile(configPath, function(err, serializedState) {
    serializedState = JSON.parse(serializedState.toString());
{'fraction_non_alphanumeric': 0.14435655613020992, 'fraction_numerical': 0.001977487070276848, 'mean_word_length': 4.98816029143898, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 15, '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': '5866791', 'n_tokens_mistral': 2012, 'n_tokens_neox': 2014, 'n_words': 425}