<commit_before>#
# This implements link hinting. Typing "F" will enter link-hinting mode, where all clickable items on the
# page have a hint marker displayed containing a sequence of letters. Typing those letters will select a link.
#
# In our 'default' mode, the characters we use to show link hints are a user-configurable option. By default
# they're the home row.  The CSS which is used on the link hints is also a configurable option.
#
# In 'filter' mode, our link hints are numbers, and the user can narrow down the range of possibilities by
# typing the text of the link itself.
#
# The "name" property below is a short-form name to appear in the link-hints mode's name.  It's for debug only.
#
isMac = KeyboardUtils.platform == "Mac"
OPEN_IN_CURRENT_TAB =
  name: "curr-tab"
  indicator: "Open link in current tab."
OPEN_IN_NEW_BG_TAB =
  name: "bg-tab"
  indicator: "Open link in new tab."
  clickModifiers: metaKey: isMac, ctrlKey: not isMac
OPEN_IN_NEW_FG_TAB =
  name: "fg-tab"
  indicator: "Open link in new tab and switch to it."
  clickModifiers: shiftKey: true, metaKey: isMac, ctrlKey: not isMac
OPEN_WITH_QUEUE =
  name: "queue"
  indicator: "Open multiple links in new tabs."
  clickModifiers: metaKey: isMac, ctrlKey: not isMac
COPY_LINK_URL =
  name: "link"
  indicator: "Copy link URL to Clipboard."
  linkActivator: (link) ->
    if link.href?
      chrome.runtime.sendMessage handler: "copyToClipboard", data: link.href
      url = link.href
      url = url[0..25] + "...." if 28 < url.length
      HUD.showForDuration "Yanked #{url}", 2000
    else
      HUD.showForDuration "No link to yank.", 2000
OPEN_INCOGNITO =
  name: "incognito"
  indicator: "Open link in incognito window."
  linkActivator: (link) -> chrome.runtime.sendMessage handler: 'openUrlInIncognito', url: link.href
DOWNLOAD_LINK_URL =
  name: "download"
  indicator: "Download link URL."
  clickModifiers: altKey: true, ctrlKey: false, metaKey: false

availableModes = [OPEN_IN_CURRENT_TAB, OPEN_IN_NEW_BG_TAB, OPEN_IN_NEW_FG_TAB, OPEN_WITH_QUEUE, COPY_LINK_URL,
  OPEN_INCOGNITO, DOWNLOAD_LINK_URL]

HintCoordinator =
  onExit: []

  sendMessage: (messageType, request = {}) ->
    Frame.postMessage "linkHintsMessage", extend request, {messageType}

  prepareToActivateMode: (mode, onExit) ->
    # We need to communicate with the background page (and other frames) to initiate link-hints mode.  To
    # prevent other Vimium commands from being triggered before link-hints mode is launched, we install a
    # temporary mode to block keyboard events.
    new SuppressAllKeyboardEvents singleton: "link-hints-mode"
    @onExit = [onExit]
    @sendMessage "prepareToActivateMode", modeIndex: availableModes.indexOf mode

  getHintDescriptors: ->
    # Ensure that the settings are loaded.  The request might have been initiated in another frame.
    Settings.onLoaded =>
      @localHints = LocalHints.getLocalHints()
      @sendMessage "postHintDescriptors", hintDescriptors:
        @localHints.map ({rect, linkText, showLinkText, hasHref, reason}, localIndex) ->
          {rect, linkText, showLinkText, hasHref, reason, frameId, localIndex}

  # We activate LinkHintsMode() in every frame and provide every frame with exactly the same hint descriptors.
  # We also propagate the key state between frames.  Therefore, the hint-selection process proceeds in lock
  # step in every frame, and @linkHintsMode is in the same state in every frame.
  activateMode: ({hintDescriptors, modeIndex, originatingFrameId}) ->
    # Ensure that the settings are loaded.  The request might have been initiated in another frame.
    Settings.onLoaded =>
      @onExit = [] unless frameId == originatingFrameId
      @linkHintsMode = new LinkHintsMode hintDescriptors, availableModes[modeIndex]

  # The following messages are exchanged between frames while link-hints mode is active.
  updateKeyState: (request) -> @linkHintsMode.updateKeyState request<commit_msg>Remove blocking mode when no hints found.<commit_after>#
# This implements link hinting. Typing "F" will enter link-hinting mode, where all clickable items on the
# page have a hint marker displayed containing a sequence of letters. Typing those letters will select a link.
#
# In our 'default' mode, the characters we use to show link hints are a user-configurable option. By default
# they're the home row.  The CSS which is used on the link hints is also a configurable option.
#
# In 'filter' mode, our link hints are numbers, and the user can narrow down the range of possibilities by
# typing the text of the link itself.
#
# The "name" property below is a short-form name to appear in the link-hints mode's name.  It's for debug only.
#
isMac = KeyboardUtils.platform == "Mac"
OPEN_IN_CURRENT_TAB =
  name: "curr-tab"
  indicator: "Open link in current tab."
OPEN_IN_NEW_BG_TAB =
  name: "bg-tab"
  indicator: "Open link in new tab."
  clickModifiers: metaKey: isMac, ctrlKey: not isMac
OPEN_IN_NEW_FG_TAB =
  name: "fg-tab"
  indicator: "Open link in new tab and switch to it."
  clickModifiers: shiftKey: true, metaKey: isMac, ctrlKey: not isMac
OPEN_WITH_QUEUE =
  name: "queue"
  indicator: "Open multiple links in new tabs."
  clickModifiers: metaKey: isMac, ctrlKey: not isMac
COPY_LINK_URL =
  name: "link"
  indicator: "Copy link URL to Clipboard."
  linkActivator: (link) ->
    if link.href?
      chrome.runtime.sendMessage handler: "copyToClipboard", data: link.href
      url = link.href
      url = url[0..25] + "...." if 28 < url.length
      HUD.showForDuration "Yanked #{url}", 2000
    else
      HUD.showForDuration "No link to yank.", 2000
OPEN_INCOGNITO =
  name: "incognito"
  indicator: "Open link in incognito window."
  linkActivator: (link) -> chrome.runtime.sendMessage handler: 'openUrlInIncognito', url: link.href
DOWNLOAD_LINK_URL =
  name: "download"
  indicator: "Download link URL."
  clickModifiers: altKey: true, ctrlKey: false, metaKey: false

availableModes = [OPEN_IN_CURRENT_TAB, OPEN_IN_NEW_BG_TAB, OPEN_IN_NEW_FG_TAB, OPEN_WITH_QUEUE, COPY_LINK_URL,
  OPEN_INCOGNITO, DOWNLOAD_LINK_URL]

HintCoordinator =
  onExit: []
  localHints: null
  suppressKeyboardEvents: null

  sendMessage: (messageType, request = {}) ->
    Frame.postMessage "linkHintsMessage", extend request, {messageType}

  prepareToActivateMode: (mode, onExit) ->
    # We need to communicate with the background page (and other frames) to initiate link-hints mode.  To
    # prevent other Vimium commands from being triggered before link-hints mode is launched, we install a
    # temporary mode to block keyboard events.
    @suppressKeyboardEvents = new SuppressAllKeyboardEvents
      name: "link-hints/suppress-keyboard-events"
      singleton: "link-hints-mode"
      indicator: "Launching hints..."
      exitOnEscape: true
    @onExit = [onExit]
    @sendMessage "prepareToActivateMode", modeIndex: availableModes.indexOf mode

  getHintDescriptors: ->
    # Ensure that the settings are loaded.  The request might have been initiated in another frame.
    Settings.onLoaded =>
      @localHints = LocalHints.getLocalHints()
      @sendMessage "postHintDescriptors", hintDescriptors:
        @localHints.map ({rect, linkText, showLinkText, hasHref, reason}, localIndex) ->
          {rect, linkText, showLinkText, hasHref, reason, frameId, localIndex}

  # We activate LinkHintsMode() in every frame and provide every frame with exactly the same hint descriptors.
  # We also propagate the key state between frames.  Therefore, the hint-selection process proceeds in lock
  # step in every frame, and @linkHintsMode is in the same state in every frame.
  activateMode: ({hintDescriptors, modeIndex, originatingFrameId}) ->
    @suppressKeyboardEvents?.exit() if @suppressKeyboardEvents?.modeIsActive
    @suppressKeyboardEvents = null
    # Ensure that the settings are loaded.  The request might have been initiated in another frame.
    Settings.onLoaded =>
      @onExit = [] unless frameId == originatingFrameId
      @linkHintsMode = new LinkHintsMode hintDescriptors, availableModes[modeIndex]

  # The following messages are exchanged between frames while link-hints mode is active.
  updateKeyState: (request) -> @linkHintsMode.updateKeyState request
{'fraction_non_alphanumeric': 0.08421436383521691, 'fraction_numerical': 0.00315955766192733, 'mean_word_length': 4.12453300124533, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6417602', 'n_tokens_mistral': 2509, 'n_tokens_neox': 2450, 'n_words': 904}