<commit_before>// Copyright 2016 The Tulsi Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import Cocoa
import TulsiGenerator


/// View controller for the editor that allows selection of BUILD files and high level options.
final class ProjectEditorPackageManagerViewController: NSViewController, NewProjectViewControllerDelegate {

  /// Indices into the Add/Remove SegmentedControl (as built by Interface Builder).
  private enum SegmentedControlButtonIndex: Int {
    case Add = 0
    case Remove = 1
  }

  @IBOutlet var packageArrayController: NSArrayController!
  @IBOutlet weak var addRemoveSegmentedControl: NSSegmentedControl!

  var newProjectSheet: NewProjectViewController! = nil
  private var newProjectNeedsSaveAs = false

  dynamic var numSelectedPackagePaths: Int = 0 {
    didSet {
      let enableRemoveButton = numSelectedPackagePaths > 0
      addRemoveSegmentedControl.setEnabled(enableRemoveButton,
                                           forSegment: SegmentedControlButtonIndex.Remove.rawValue)
    }
  }

  deinit {
    unbind("numSelectedPackagePaths")
  }

  override func loadView() {
    NSValueTransformer.setValueTransformer(PackagePathValueTransformer(),
                                           forName: "PackagePathValueTransformer")
    super.loadView()
    bind("numSelectedPackagePaths",
         toObject: packageArrayController,
         withKeyPath: "selectedObjects.@count",
         options: nil)
  }

  override func viewDidAppear() {
    super.viewDidAppear()
    let document = representedObject as! TulsiProjectDocument

    // Start the new project flow if the associated document is not linked to a project.
    if document.fileURL != nil || document.project != nil { return }
    newProjectSheet = NewProjectViewController()
    newProjectSheet.delegate = self

    // Present the NewProjectViewController as a sheet.
    // This is done via dispatch_async because we want it to happen after the window appearance
    // animation is complete.
    dispatch_async(dispatch_get_main_queue(), {
      self.presentViewControllerAsSheet(self.newProjectSheet)
    })
  }

  @IBAction func didClickAddRemoveSegmentedControl(sender: NSSegmentedCell) {
    // Ignore mouse up messages.
    if sender.selectedSegment < 0 { return }

    guard let button = SegmentedControlButtonIndex(rawValue: sender.selectedSegment) else {
      assertionFailure("Unexpected add/remove button index \(sender.selectedSegment)")
      return
    }

    switch button {
      case .Add:
        didClickAddBUILDFile(sender)
      case .Remove:
        didClickRemoveSelectedBUILDFiles(sender)
    }
  }

  func didClickAddBUILDFile(sender: AnyObject?) {
    guard let document = self.representedObject as? TulsiProjectDocument,
              workspacePath = document.workspaceRootURL?.path else {
      return
    }

    let panel = FilteredOpenPanel.filteredOpenPanel() {
      (_: AnyObject, url: NSURL) -> Bool in
        var isDir: AnyObject?
        var isPackage: AnyObject?
        do {
          try url.getResourceValue(&isDir, forKey: NSURLIsDirectoryKey)
          try url.getResourceValue(&isPackage, forKey: NSURLIsPackageKey)
          if let isDir = isDir as? NSNumber, isPackage = isPackage as? NSNumber
              where !isPackage.boolValue {
            if isDir.boolValue { return true }
            if let filename = url.lastPathComponent where filename == "BUILD" {
              // Prevent anything outside of the selected workspace.
              return url.path!.hasPrefix(workspacePath) && !document.containsBUILDFileURL(url)
            }
          }
        } catch _ {
          // Treat any exception as an invalid URL.
        }
        return false
    }

    panel.prompt = NSLocalizedString("ProjectEditor_AddBUILDFilePrompt",
                                     comment: "Label for the button used to confirm adding the selected BUILD file to the Tulsi project.")
    panel.canChooseDirectories = false
    panel.beginSheetModalForWindow(self.view.window!) { value in
      if value == NSFileHandlingPanelOKButton {
        guard let URL = panel.URL else {
          return
        }
        if !document.addBUILDFileURL(URL) {
          NSBeep()
        }
      }
    }
  }

  func didClickRemoveSelectedBUILDFiles(sender: AnyObject?) {<commit_msg>Support adding packages with BUILD.bazel filenames<commit_after>// Copyright 2016 The Tulsi Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import Cocoa
import TulsiGenerator


/// View controller for the editor that allows selection of BUILD files and high level options.
final class ProjectEditorPackageManagerViewController: NSViewController, NewProjectViewControllerDelegate {

  /// Indices into the Add/Remove SegmentedControl (as built by Interface Builder).
  private enum SegmentedControlButtonIndex: Int {
    case Add = 0
    case Remove = 1
  }

  @IBOutlet var packageArrayController: NSArrayController!
  @IBOutlet weak var addRemoveSegmentedControl: NSSegmentedControl!

  var newProjectSheet: NewProjectViewController! = nil
  private var newProjectNeedsSaveAs = false

  dynamic var numSelectedPackagePaths: Int = 0 {
    didSet {
      let enableRemoveButton = numSelectedPackagePaths > 0
      addRemoveSegmentedControl.setEnabled(enableRemoveButton,
                                           forSegment: SegmentedControlButtonIndex.Remove.rawValue)
    }
  }

  deinit {
    unbind("numSelectedPackagePaths")
  }

  override func loadView() {
    NSValueTransformer.setValueTransformer(PackagePathValueTransformer(),
                                           forName: "PackagePathValueTransformer")
    super.loadView()
    bind("numSelectedPackagePaths",
         toObject: packageArrayController,
         withKeyPath: "selectedObjects.@count",
         options: nil)
  }

  override func viewDidAppear() {
    super.viewDidAppear()
    let document = representedObject as! TulsiProjectDocument

    // Start the new project flow if the associated document is not linked to a project.
    if document.fileURL != nil || document.project != nil { return }
    newProjectSheet = NewProjectViewController()
    newProjectSheet.delegate = self

    // Present the NewProjectViewController as a sheet.
    // This is done via dispatch_async because we want it to happen after the window appearance
    // animation is complete.
    dispatch_async(dispatch_get_main_queue(), {
      self.presentViewControllerAsSheet(self.newProjectSheet)
    })
  }

  @IBAction func didClickAddRemoveSegmentedControl(sender: NSSegmentedCell) {
    // Ignore mouse up messages.
    if sender.selectedSegment < 0 { return }

    guard let button = SegmentedControlButtonIndex(rawValue: sender.selectedSegment) else {
      assertionFailure("Unexpected add/remove button index \(sender.selectedSegment)")
      return
    }

    switch button {
      case .Add:
        didClickAddBUILDFile(sender)
      case .Remove:
        didClickRemoveSelectedBUILDFiles(sender)
    }
  }

  func didClickAddBUILDFile(sender: AnyObject?) {
    guard let document = self.representedObject as? TulsiProjectDocument,
              workspacePath = document.workspaceRootURL?.path else {
      return
    }

    let panel = FilteredOpenPanel.filteredOpenPanel() {
      (_: AnyObject, url: NSURL) -> Bool in
        var isDir: AnyObject?
        var isPackage: AnyObject?
        do {
          try url.getResourceValue(&isDir, forKey: NSURLIsDirectoryKey)
          try url.getResourceValue(&isPackage, forKey: NSURLIsPackageKey)
          if let isDir = isDir as? NSNumber, isPackage = isPackage as? NSNumber
              where !isPackage.boolValue {
            if isDir.boolValue { return true }
            if let filename = url.lastPathComponent where (filename == "BUILD" || filename == "BUILD.bazel") {
              // Prevent anything outside of the selected workspace.
              return url.path!.hasPrefix(workspacePath) && !document.containsBUILDFileURL(url)
            }
          }
        } catch _ {
          // Treat any exception as an invalid URL.
        }
        return false
    }

    panel.prompt = NSLocalizedString("ProjectEditor_AddBUILDFilePrompt",
                                     comment: "Label for the button used to confirm adding the selected BUILD file to the Tulsi project.")
    panel.canChooseDirectories = false
    panel.beginSheetModalForWindow(self.view.window!) { value in
      if value == NSFileHandlingPanelOKButton {
        guard let URL = panel.URL else {
          return
        }
        if !document.addBUILDFileURL(URL) {
          NSBeep()
        }
      }
    }
  }

  func didClickRemoveSelectedBUILDFiles(sender: AnyObject?) {
{'fraction_non_alphanumeric': 0.0722176759410802, 'fraction_numerical': 0.0026595744680851063, 'mean_word_length': 2.8431603773584904, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7056655', 'n_tokens_mistral': 2548, 'n_tokens_neox': 2447, 'n_words': 781}