<commit_before>// Copyright (c) 2013, Google Inc. Please see the AUTHORS file for details.
// All rights reserved. Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/**
 * An entrypoint to the [ace.dart](https://github.com/rmsmith/ace.dart) package.
 */
library spark.ace;

import 'dart:async';
import 'dart:html' as html;
import 'dart:js' as js;
import 'dart:math' as math;

import 'package:ace/ace.dart' as ace;
import 'package:ace/proxy.dart';
import 'package:crypto/crypto.dart' as crypto;
import 'package:path/path.dart' as path;

import '../spark_flags.dart';
import 'css/cssbeautify.dart';
import 'editors.dart';
import 'navigation.dart';
import 'package_mgmt/bower_properties.dart';
import 'package_mgmt/pub_properties.dart';
import 'platform_info.dart';
import 'preferences.dart';
import 'utils.dart' as utils;
import 'workspace.dart' as workspace;
import 'services.dart' as svc;
import 'outline.dart';
import 'ui/polymer/goto_line_view/goto_line_view.dart';
import 'utils.dart';

export 'package:ace/ace.dart' show EditSession;

class TextEditor extends Editor {
  static final RegExp whitespaceRegEx = new RegExp('[\t ]*\$', multiLine:true);

  final AceManager aceManager;
  final workspace.File file;

  StreamSubscription _aceSubscription;
  StreamController _dirtyController = new StreamController.broadcast();
  StreamController _modificationController = new StreamController.broadcast();
  Completer<TextEditor> _whenReadyCompleter = new Completer();

  final SparkPreferences _prefs;
  ace.EditSession _session;

  String _lastSavedHash;

  bool _dirty = false;

  factory TextEditor(AceManager aceManager, workspace.File file,
      SparkPreferences prefs) {
    if (DartEditor.isDartFile(file)) {
      return new DartEditor._create(aceManager, file, prefs);
    }
    if (CssEditor.isCssFile(file)) {
      return new CssEditor._create(aceManager, file, prefs);
    }
    return new TextEditor._create(aceManager, file, prefs);
  }
  
  TextEditor._create(this.aceManager, this.file, this._prefs);

  Future<TextEditor> get whenReady => _whenReadyCompleter.future;
  
  void setSession(ace.EditSession value) {
    _session = value;
    if (_aceSubscription != null) _aceSubscription.cancel();
    _aceSubscription = _session.onChange.listen((_) => dirty = true);
    if (!_whenReadyCompleter.isCompleted) _whenReadyCompleter.complete(this);
  }

  bool get dirty => _dirty;

  Stream get onDirtyChange => _dirtyController.stream;
  Stream get onModification => _modificationController.stream;

  set dirty(bool value) {
    if (value != _dirty) {
      _dirty = value;
      _dirtyController.add(value);
    }
    _modificationController.add(dirty);
  }

  html.Element get element => aceManager.parentElement;

  void activate() {
    aceManager.outline.visible = supportsOutline;
    aceManager._aceEditor.readOnly = readOnly;
  }

  void deactivate() { }

  void resize() => aceManager.resize();

  void focus() => aceManager.focus();

  void select(Span selection) {
    // Check if we're the current editor.
    if (file != aceManager.currentFile) return;

    ace.Point startSelection = _session.document.indexToPosition(selection.offset);
    ace.Point endSelection = _session.document.indexToPosition(
        selection.offset + selection.length);

    aceManager._aceEditor.gotoLine(startSelection.row);

    ace.Selection aceSel = aceManager._aceEditor.selection;
    aceSel.setSelectionAnchor(startSelection.row, startSelection.column);
    aceSel.selectTo(endSelection.row, endSelection.column);
  }

  bool get supportsOutline => false;

  bool get supportsFormat => false;

  // TODO(ussuri): use MetaPackageManager instead when it's ready.
  bool get readOnly => pubProperties.isInPackagesFolder(file) ||
      bowerProperties.isInPackagesFolder(file);

  void format() { }

  void navigateToDeclaration() { }

  void fileContentsChanged() {
    print("fileContentsChanged");
    if (_session != null) {
      // Check that we didn't cause this change event.
      file.getContents().then((String text) {
        String fileContentsHash = _calcMD5(text);

        if (fileContentsHash != _lastSavedHash) {
          _lastSavedHash = fileContentsHash;
          _replaceContents(text);
        }
      });
    }
  }

  Future save() {
    // We store a hash of the contents when saving. When we get a change
    // notification (in fileContentsChanged()), we compare the last write to the
    // contents on disk.
    if (_dirty) {
      // Remove the trailing whitespace if asked to do so.
      // TODO(ericarnold): Can't think of an easy way to share this preference,
      //           but it might be a good idea to do so rather than passing it.

      String text = _session.value;

      if (_prefs.stripWhitespaceOnSave) text =
          text.replaceAll(whitespaceRegEx, '');
      _lastSavedHash = _calcMD5(text);<commit_msg>removed print statement<commit_after>// Copyright (c) 2013, Google Inc. Please see the AUTHORS file for details.
// All rights reserved. Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/**
 * An entrypoint to the [ace.dart](https://github.com/rmsmith/ace.dart) package.
 */
library spark.ace;

import 'dart:async';
import 'dart:html' as html;
import 'dart:js' as js;
import 'dart:math' as math;

import 'package:ace/ace.dart' as ace;
import 'package:ace/proxy.dart';
import 'package:crypto/crypto.dart' as crypto;
import 'package:path/path.dart' as path;

import '../spark_flags.dart';
import 'css/cssbeautify.dart';
import 'editors.dart';
import 'navigation.dart';
import 'package_mgmt/bower_properties.dart';
import 'package_mgmt/pub_properties.dart';
import 'platform_info.dart';
import 'preferences.dart';
import 'utils.dart' as utils;
import 'workspace.dart' as workspace;
import 'services.dart' as svc;
import 'outline.dart';
import 'ui/polymer/goto_line_view/goto_line_view.dart';
import 'utils.dart';

export 'package:ace/ace.dart' show EditSession;

class TextEditor extends Editor {
  static final RegExp whitespaceRegEx = new RegExp('[\t ]*\$', multiLine:true);

  final AceManager aceManager;
  final workspace.File file;

  StreamSubscription _aceSubscription;
  StreamController _dirtyController = new StreamController.broadcast();
  StreamController _modificationController = new StreamController.broadcast();
  Completer<TextEditor> _whenReadyCompleter = new Completer();

  final SparkPreferences _prefs;
  ace.EditSession _session;

  String _lastSavedHash;

  bool _dirty = false;

  factory TextEditor(AceManager aceManager, workspace.File file,
      SparkPreferences prefs) {
    if (DartEditor.isDartFile(file)) {
      return new DartEditor._create(aceManager, file, prefs);
    }
    if (CssEditor.isCssFile(file)) {
      return new CssEditor._create(aceManager, file, prefs);
    }
    return new TextEditor._create(aceManager, file, prefs);
  }
  
  TextEditor._create(this.aceManager, this.file, this._prefs);

  Future<TextEditor> get whenReady => _whenReadyCompleter.future;
  
  void setSession(ace.EditSession value) {
    _session = value;
    if (_aceSubscription != null) _aceSubscription.cancel();
    _aceSubscription = _session.onChange.listen((_) => dirty = true);
    if (!_whenReadyCompleter.isCompleted) _whenReadyCompleter.complete(this);
  }

  bool get dirty => _dirty;

  Stream get onDirtyChange => _dirtyController.stream;
  Stream get onModification => _modificationController.stream;

  set dirty(bool value) {
    if (value != _dirty) {
      _dirty = value;
      _dirtyController.add(value);
    }
    _modificationController.add(dirty);
  }

  html.Element get element => aceManager.parentElement;

  void activate() {
    aceManager.outline.visible = supportsOutline;
    aceManager._aceEditor.readOnly = readOnly;
  }

  void deactivate() { }

  void resize() => aceManager.resize();

  void focus() => aceManager.focus();

  void select(Span selection) {
    // Check if we're the current editor.
    if (file != aceManager.currentFile) return;

    ace.Point startSelection = _session.document.indexToPosition(selection.offset);
    ace.Point endSelection = _session.document.indexToPosition(
        selection.offset + selection.length);

    aceManager._aceEditor.gotoLine(startSelection.row);

    ace.Selection aceSel = aceManager._aceEditor.selection;
    aceSel.setSelectionAnchor(startSelection.row, startSelection.column);
    aceSel.selectTo(endSelection.row, endSelection.column);
  }

  bool get supportsOutline => false;

  bool get supportsFormat => false;

  // TODO(ussuri): use MetaPackageManager instead when it's ready.
  bool get readOnly => pubProperties.isInPackagesFolder(file) ||
      bowerProperties.isInPackagesFolder(file);

  void format() { }

  void navigateToDeclaration() { }

  void fileContentsChanged() {
    if (_session != null) {
      // Check that we didn't cause this change event.
      file.getContents().then((String text) {
        String fileContentsHash = _calcMD5(text);

        if (fileContentsHash != _lastSavedHash) {
          _lastSavedHash = fileContentsHash;
          _replaceContents(text);
        }
      });
    }
  }

  Future save() {
    // We store a hash of the contents when saving. When we get a change
    // notification (in fileContentsChanged()), we compare the last write to the
    // contents on disk.
    if (_dirty) {
      // Remove the trailing whitespace if asked to do so.
      // TODO(ericarnold): Can't think of an easy way to share this preference,
      //           but it might be a good idea to do so rather than passing it.

      String text = _session.value;

      if (_prefs.stripWhitespaceOnSave) text =
          text.replaceAll(whitespaceRegEx, '');
      _lastSavedHash = _calcMD5(text);
{'fraction_non_alphanumeric': 0.10743380855397149, 'fraction_numerical': 0.0012219959266802445, 'mean_word_length': 3.8236738703339883, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 29, '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': '6095927', 'n_tokens_mistral': 3013, 'n_tokens_neox': 2931, 'n_words': 782}