<commit_before># NW.js-specific initialisation
if process?
  gui = require 'nw.gui'; crypto = require 'crypto'; fs = require 'fs'; nomnom = require 'nomnom'
  path = require 'path'; {spawn} = require 'child_process'; proxy = require './proxy'

  segmentsIntersect = (a, b, c, d) -> a < d && c < b

  rectanglesIntersect = (r0, r1) -> (
    segmentsIntersect(r0.x, r0.x + r0.width,  r1.x, r1.x + r1.width) &&
    segmentsIntersect(r0.y, r0.y + r0.height, r1.y, r1.y + r1.height)
  )

  segmentFitWithin = (a, b, A, B) ->
    if b - a > B - A then [A, B] else if a < A then [A, A + b - a] else if b > B then [B - b + a, B] else [a, b]

  rectangleFitWithin = (r, R) ->
    [x, x1] = segmentFitWithin r.x, r.x + r.width,  R.x, R.x + R.width
    [y, y1] = segmentFitWithin r.y, r.y + r.height, R.y, R.y + R.height
    {x, y, width: x1 - x, height: y1 - y}

  restoreWindow = (w, r) -> # w: NWJS window, r: rectangle
    for scr in gui.Screen.screens when rectanglesIntersect scr.work_area, r
      r = rectangleFitWithin r, scr.work_area
      w.moveTo r.x, r.y; w.resizeTo r.width, r.height
      process.nextTick ->
        w.dx = w.x      - r.x
        w.dy = w.y      - r.y
        w.dw = w.width  - r.width
        w.dh = w.height - r.height
        return
      break
    return

  D.nwjs = true; D.mac = process.platform == 'darwin'; D.floating = !!opener
  if D.mac then process.env.DYALOG_IDE_INTERPRETER_EXE ||= path.resolve process.cwd(), '../Dyalog/mapl'
  process.chdir process.env.PWD || process.env.HOME || '.' # see https://github.com/nwjs/nw.js/issues/648
  D.process = process; gui.Screen.Init(); nww = gui.Window.get()

  urlParams = {}
  for kv in (location + '').replace(/^[^\?]*($|\?)/, '').split '&'
    [_, k, v] = /^([^=]*)=?(.*)$/.exec kv; urlParams[unescape(k or '')] = unescape(v or '')

  do -> # restore window state:
    if D.floating
      opener.D.floatingWindows.push nww
      restoreWindow nww,
        x:      +urlParams.x
        y:      +urlParams.y
        width:  +urlParams.width
        height: +urlParams.height
    else
      D.floatingWindows = []; D.editorsOnTop = 0
      nww.on 'focus', -> (for x in D.floatingWindows then x.setAlwaysOnTop !!D.editorsOnTop); return
      nww.on 'blur',  -> (for x in D.floatingWindows then x.setAlwaysOnTop false           ); return
      if localStorage.pos then try
        pos = JSON.parse localStorage.pos
        restoreWindow nww, x: pos[0], y: pos[1], width: pos[2], height: pos[3]
    return
  nww.show(); nww.focus() # focus() is needed for the Mac

  throttle = (f) -> tid = null; -> tid ?= setTimeout (-> f(); tid = null; return), 500; return
  saveWindowState = throttle ->
    posStr = JSON.stringify [
      nww.x      - (nww.dx || 0)
      nww.y      - (nww.dy || 0)
      nww.width  - (nww.dw || 0)
      nww.height - (nww.dh || 0)
    ]
    if D.floating
      (fw = opener.D.floatingWindows).splice fw.indexOf(nww), 1
      if +urlParams.tracer || urlParams.token == '1'
        if +urlParams.tracer then localStorage.posTracer = posStr else localStorage.posEditor = posStr
    else
      localStorage.pos = posStr
    return
  nww.on 'move',   saveWindowState
  nww.on 'resize', saveWindowState

  nww.on 'close', ->
    if D.forceClose
      process.nextTick -> nww.close true; return
    else
      window.onbeforeunload?(); if !D.floating then process.nextTick -> nww.close true; return
    return

  $ ->
    contextMenu = null
    $ document
      .on 'keydown', '*', 'f12', -> nww.showDevTools(); false
      .on 'contextmenu', (e) ->
        if !contextMenu
          contextMenu = new gui.Menu
          ['Cut', 'Copy', 'Paste'].forEach (x) ->
            contextMenu.append new gui.MenuItem label: x, click: (-> document.execCommand x; return); return
        contextMenu.popup e.clientX, e.clientY
        false
    return

  D.readFile = fs.readFile

  # external editors (available only under nwjs)
  tmpDir = process.env.TMPDIR || process.env.TMP || process.env.TEMP || '/tmp'
  if editorExe = process.env.DYALOG_IDE_EDITOR || process.env.EDITOR
    D.openInExternalEditor = (text, line, callback) ->
      tmpFile = path.join tmpDir, "#{crypto.randomBytes(8).toString 'hex'}.dyalog"
      callback0 = callback
      callback = (args...) -> fs.unlink tmpFile, -> callback0 args... # make sure to delete file before calling callback
      fs.writeFile tmpFile, text, {mode: 0o600}, (err) ->
        if err then callback err; return
        child = spawn editorExe, [tmpFile], cwd: tmpDir, env: $.extend {}, process.env,
          DYALOG_IDE_FILE: tmpFile
          DYALOG_IDE_LINE_NUMBER: 1 + line
        child.on 'error', callback
        child.on 'exit', (c, s) ->
          if c || s then callback('Editor exited with ' + if c then 'code ' + c else 'signal ' + s); return
          fs.readFile tmpFile, 'utf8', callback; return
        return
      return

  D.createSocket = ->
    class LocalSocket
      emit: (a...) -> @other.onevent data: a
      onevent: ({data}) -> (for f in @[data[0]] or [] then f data[1..]...); return
      on: (e, f) -> (@[e] ?= []).push f; @
    socket = new LocalSocket; socket1 = new LocalSocket; socket.other = socket1; socket1.other = socket
    proxy.Proxy() socket1
    socket

  {execPath} = process; if D.mac then execPath = execPath.replace /(\/Contents\/).*$/, '$1MacOS/node-webkit'<commit_msg>init-nw.coffee: revised the code and added comments<commit_after># NW.js-specific initialisation
if process?
  gui = require 'nw.gui'; crypto = require 'crypto'; fs = require 'fs'; nomnom = require 'nomnom'
  path = require 'path'; {spawn} = require 'child_process'; proxy = require './proxy'

  segmOverlap = (a, b, c, d) -> a < d && c < b # Do the two segments ab and cd overlap?

  rectOverlap = (r0, r1) -> ( # A rectangle is {x,y,width,height}.  Do the two overlap?
    segmOverlap(r0.x, r0.x + r0.width,  r1.x, r1.x + r1.width) &&
    segmOverlap(r0.y, r0.y + r0.height, r1.y, r1.y + r1.height)
  )

  segmFit = (a, b, A, B) -> # Nudge and/or squeeze "ab" as necessary so it fits into "AB".
    if b - a > B - A then [A, B] else if a < A then [A, A + b - a] else if b > B then [B - b + a, B] else [a, b]

  rectFit = (r, R) -> # like segmFit but for for rectangles
    [x, x1] = segmFit r.x, r.x + r.width,  R.x, R.x + R.width
    [y, y1] = segmFit r.y, r.y + r.height, R.y, R.y + R.height
    {x, y, width: x1 - x, height: y1 - y}

  restoreWindow = (w, r) -> # w: NWJS window, r: rectangle
    # Find a screen that overlaps with "r" and fit "w" inside it:
    for scr in gui.Screen.screens when rectOverlap scr.work_area, r
      r = rectFit r, scr.work_area
      w.moveTo r.x, r.y; w.resizeTo r.width, r.height
      process.nextTick ->
        w.dx = w.x      - r.x
        w.dy = w.y      - r.y
        w.dw = w.width  - r.width
        w.dh = w.height - r.height
        return
      break
    return

  D.nwjs = true; D.mac = process.platform == 'darwin'; D.floating = !!opener
  if D.mac then process.env.DYALOG_IDE_INTERPRETER_EXE ||= path.resolve process.cwd(), '../Dyalog/mapl'
  process.chdir process.env.PWD || process.env.HOME || '.' # see https://github.com/nwjs/nw.js/issues/648
  D.process = process; gui.Screen.Init(); nww = gui.Window.get()

  urlParams = {}
  for kv in (location + '').replace(/^[^\?]*($|\?)/, '').split '&'
    [_, k, v] = /^([^=]*)=?(.*)$/.exec kv; urlParams[unescape k || ''] = unescape v || ''

  do -> # restore window state:
    if D.floating
      opener.D.floatingWindows.push nww
      restoreWindow nww,
        x:      +urlParams.x
        y:      +urlParams.y
        width:  +urlParams.width
        height: +urlParams.height
    else
      D.floatingWindows = []; D.editorsOnTop = 0
      nww.on 'focus', -> (for x in D.floatingWindows then x.setAlwaysOnTop !!D.editorsOnTop); return
      nww.on 'blur',  -> (for x in D.floatingWindows then x.setAlwaysOnTop false           ); return
      if localStorage.pos then try
        pos = JSON.parse localStorage.pos
        restoreWindow nww, x: pos[0], y: pos[1], width: pos[2], height: pos[3]
    return
  nww.show(); nww.focus() # focus() is needed for the Mac

  # To "throttle" a function is to make it execute no more often than once every X milliseconds.
  throttle = (f) -> tid = null; -> tid ?= setTimeout (-> f(); tid = null; return), 500; return

  saveWindowState = throttle ->
    posStr = JSON.stringify [
      nww.x      - (nww.dx || 0)
      nww.y      - (nww.dy || 0)
      nww.width  - (nww.dw || 0)
      nww.height - (nww.dh || 0)
    ]
    if D.floating
      (fw = opener.D.floatingWindows).splice fw.indexOf(nww), 1
      if +urlParams.tracer || urlParams.token == '1'
        if +urlParams.tracer then localStorage.posTracer = posStr else localStorage.posEditor = posStr
    else
      localStorage.pos = posStr
    return
  nww.on 'move',   saveWindowState
  nww.on 'resize', saveWindowState

  nww.on 'close', ->
    if D.forceClose
      process.nextTick -> nww.close true; return
    else
      window.onbeforeunload?(); if !D.floating then process.nextTick -> nww.close true; return
    return

  $ ->
    cmenu = null # context menu on right-click, lazily initialized
    $ document
      .on 'keydown', '*', 'f12', -> nww.showDevTools(); false
      .on 'contextmenu', (e) ->
        if !cmenu
          cmenu = new gui.Menu
          ['Cut', 'Copy', 'Paste'].forEach (x) ->
            cmenu.append new gui.MenuItem label: x, click: (-> document.execCommand x; return); return
        cmenu.popup e.clientX, e.clientY
        false
    return

  D.readFile = fs.readFile # needed for presentation mode

  # external editors (available only under nwjs)
  tmpDir = process.env.TMPDIR || process.env.TMP || process.env.TEMP || '/tmp'
  if editorExe = process.env.DYALOG_IDE_EDITOR || process.env.EDITOR
    D.openInExternalEditor = (text, line, callback) ->
      tmpFile = path.join tmpDir, "#{crypto.randomBytes(8).toString 'hex'}.dyalog"
      callback0 = callback
      callback = (args...) -> fs.unlink tmpFile, -> callback0 args... # make sure to delete file before calling callback
      fs.writeFile tmpFile, text, {mode: 0o600}, (err) ->
        if err then callback err; return
        child = spawn editorExe, [tmpFile], cwd: tmpDir, env: $.extend {}, process.env,
          DYALOG_IDE_FILE: tmpFile
          DYALOG_IDE_LINE_NUMBER: 1 + line
        child.on 'error', callback
        child.on 'exit', (c, s) ->
          if c || s then callback('Editor exited with ' + if c then 'code ' + c else 'signal ' + s); return
          fs.readFile tmpFile, 'utf8', callback; return
        return
      return

  D.createSocket = ->
    class LocalSocket # imitate socket.io's API
      emit: (a...) -> @other.onevent data: a
      onevent: ({data}) -> (for f in @[data[0]] or [] then f data[1..]...); return
      on: (e, f) -> (@[e] ?= []).push f; @
    socket = new LocalSocket; socket1 = new LocalSocket; socket.other = socket1; socket1.other = socket
    proxy.Proxy() socket1
    socket

  {execPath} = process; if D.mac then execPath = execPath.replace /(\/Contents\/).*$/, '$1MacOS/node-webkit'
{'fraction_non_alphanumeric': 0.15365193868349863, 'fraction_numerical': 0.009558160504959423, 'mean_word_length': 2.4031911629334153, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 67, 'https://': 2, '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': '601579', 'n_tokens_mistral': 4026, 'n_tokens_neox': 3891, 'n_words': 1112}