<commit_before>_ = require 'underscore-plus'
path = require 'path'
guid = require 'guid'
{Model, Point, Range} = require 'telepath'
LanguageMode = require './language-mode'
DisplayBuffer = require './display-buffer'
Cursor = require './cursor'
Selection = require './selection'
TextMateScopeSelector = require('first-mate').ScopeSelector

# Public: The core model of Atom.
#
# An {Editor} represents a unique view of each document, with its own
# {Cursor}s and scroll position.
#
# For instance if a user creates a split, Atom creates a second {Editor}
# but both {Editor}s interact with the same buffer underlying buffer. So
# if you type in either buffer it immediately appears in both but if you scroll
# in one it doesn't scroll the other.
#
# Almost all extension will interact primiarily with this class as it provides
# access to objects you'll most commonly interact with. To access it you'll
# want to register a callback on {WorkspaceView} which will be fired once for every
# existing {Editor} as well as any future {Editor}s.
#
# ## Example
# ```coffeescript
#   atom.workspaceView.eachEditorView (editorView) ->
#     editorView.insertText('Hello World')
# ```
#
# ## Collaboration builtin
#
# FIXME: Describe how there are both local and remote cursors and selections and
# why that is.
module.exports =
class Editor extends Model

  @properties
    displayBuffer: null
    softTabs: null
    scrollTop: 0
    scrollLeft: 0

  deserializing: false
  callDisplayBufferCreatedHook: false
  buffer: null
  languageMode: null
  cursors: null
  remoteCursors: null
  selections: null
  remoteSelections: null
  suppressSelectionMerging: false

  constructor: ->
    super
    @deserializing = @state?

  created: ->
    if @deserializing
      @deserializing = false
      @callDisplayBufferCreatedHook = true
      return

    @cursors = []
    @remoteCursors = []
    @selections = []
    @remoteSelections = []

    unless @displayBuffer?
      @displayBuffer = new DisplayBuffer({@buffer, @tabLength, @softWrap})
      @softTabs = @buffer.usesSoftTabs() ? @softTabs ? atom.config.get('editor.softTabs') ? true

    @displayBuffer.created() if @callDisplayBufferCreatedHook
    @buffer = @displayBuffer.buffer

    for marker in @findMarkers(@getSelectionMarkerAttributes())
      marker.setAttributes(preserveFolds: true)
      @addSelection(marker)

    @subscribeToBuffer()
    @subscribeToDisplayBuffer()

    if @getCursors().length is 0 and not @suppressCursorCreation
      if @initialLine
        position = [@initialLine, 0]
      else
        position = _.last(@getRemoteCursors())?.getBufferPosition() ? [0, 0]
      @addCursorAtBufferPosition(position)

    @languageMode = new LanguageMode(this, @buffer.getExtension())
    @subscribe @state, 'changed', ({newValues}) =>
      for key, newValue of newValues
        switch key
          when 'scrollTop'
            @emit 'scroll-top-changed', newValue
          when 'scrollLeft'
            @emit 'scroll-left-changed', newValue

  # Deprecated: The goal is a world where we don't call serialize explicitly
  serialize: -> this

  # Private:
  subscribeToBuffer: ->
    @buffer.retain()
    @subscribe @buffer, "path-changed", =>
      unless atom.project.getPath()?
        atom.project.setPath(path.dirname(@getPath()))
      @emit "title-changed"
      @emit "path-changed"
    @subscribe @buffer, "contents-modified", => @emit "contents-modified"
    @subscribe @buffer, "contents-conflicted", => @emit "contents-conflicted"
    @subscribe @buffer, "modified-status-changed", => @emit "modified-status-changed"
    @preserveCursorPositionOnBufferReload()<commit_msg>Observe scroll* behaviors instead of the entire state document<commit_after>_ = require 'underscore-plus'
path = require 'path'
guid = require 'guid'
{Model, Point, Range} = require 'telepath'
LanguageMode = require './language-mode'
DisplayBuffer = require './display-buffer'
Cursor = require './cursor'
Selection = require './selection'
TextMateScopeSelector = require('first-mate').ScopeSelector

# Public: The core model of Atom.
#
# An {Editor} represents a unique view of each document, with its own
# {Cursor}s and scroll position.
#
# For instance if a user creates a split, Atom creates a second {Editor}
# but both {Editor}s interact with the same buffer underlying buffer. So
# if you type in either buffer it immediately appears in both but if you scroll
# in one it doesn't scroll the other.
#
# Almost all extension will interact primiarily with this class as it provides
# access to objects you'll most commonly interact with. To access it you'll
# want to register a callback on {WorkspaceView} which will be fired once for every
# existing {Editor} as well as any future {Editor}s.
#
# ## Example
# ```coffeescript
#   atom.workspaceView.eachEditorView (editorView) ->
#     editorView.insertText('Hello World')
# ```
#
# ## Collaboration builtin
#
# FIXME: Describe how there are both local and remote cursors and selections and
# why that is.
module.exports =
class Editor extends Model

  @properties
    displayBuffer: null
    softTabs: null
    scrollTop: 0
    scrollLeft: 0

  deserializing: false
  callDisplayBufferCreatedHook: false
  buffer: null
  languageMode: null
  cursors: null
  remoteCursors: null
  selections: null
  remoteSelections: null
  suppressSelectionMerging: false

  constructor: ->
    super
    @deserializing = @state?

  created: ->
    if @deserializing
      @deserializing = false
      @callDisplayBufferCreatedHook = true
      return

    @cursors = []
    @remoteCursors = []
    @selections = []
    @remoteSelections = []

    unless @displayBuffer?
      @displayBuffer = new DisplayBuffer({@buffer, @tabLength, @softWrap})
      @softTabs = @buffer.usesSoftTabs() ? @softTabs ? atom.config.get('editor.softTabs') ? true

    @displayBuffer.created() if @callDisplayBufferCreatedHook
    @buffer = @displayBuffer.buffer

    for marker in @findMarkers(@getSelectionMarkerAttributes())
      marker.setAttributes(preserveFolds: true)
      @addSelection(marker)

    @subscribeToBuffer()
    @subscribeToDisplayBuffer()

    if @getCursors().length is 0 and not @suppressCursorCreation
      if @initialLine
        position = [@initialLine, 0]
      else
        position = _.last(@getRemoteCursors())?.getBufferPosition() ? [0, 0]
      @addCursorAtBufferPosition(position)

    @languageMode = new LanguageMode(this, @buffer.getExtension())

    @subscribe @$scrollTop, 'value', (scrollTop) => @emit 'scroll-top-changed', scrollTop
    @subscribe @$scrollLeft, 'value', (scrollLeft) => @emit 'scroll-left-changed', scrollLeft

  # Deprecated: The goal is a world where we don't call serialize explicitly
  serialize: -> this

  # Private:
  subscribeToBuffer: ->
    @buffer.retain()
    @subscribe @buffer, "path-changed", =>
      unless atom.project.getPath()?
        atom.project.setPath(path.dirname(@getPath()))
      @emit "title-changed"
      @emit "path-changed"
    @subscribe @buffer, "contents-modified", => @emit "contents-modified"
    @subscribe @buffer, "contents-conflicted", => @emit "contents-conflicted"
    @subscribe @buffer, "modified-status-changed", => @emit "modified-status-changed"
    @preserveCursorPositionOnBufferReload()
{'fraction_non_alphanumeric': 0.10705930920599972, 'fraction_numerical': 0.001651300399064263, 'mean_word_length': 3.858288770053476, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 24, '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': '719921', 'n_tokens_mistral': 2093, 'n_tokens_neox': 2035, 'n_words': 652}