text:
/**
 * @file
 * Drupal's Settings Tray library.
 */

(function ($, Drupal) {

  'use strict';

  var blockConfigureSelector = '[data-outside-in-edit]';
  var toggleEditSelector = '[data-drupal-outsidein="toggle"]';
  var itemsToToggleSelector = '#main-canvas, #toolbar-bar, [data-drupal-outsidein="editable"] a, [data-drupal-outsidein="editable"] button';
  var contextualItemsSelector = '[data-contextual-id] a, [data-contextual-id] button';

  /**
   * Reacts to contextual links being added.
   *
   * @param {jQuery.Event} event
   *   The `drupalContextualLinkAdded` event.
   * @param {object} data
   *   An object containing the data relevant to the event.
   *
   * @listens event:drupalContextualLinkAdded
   */
  $(document).on('drupalContextualLinkAdded', function (event, data) {
    // Bind Ajax behaviors to all items showing the class.
    // @todo Fix contextual links to work with use-ajax links in
    //    https://www.drupal.org/node/2764931.
    Drupal.attachBehaviors(data.$el[0]);

    // Bind a listener to all 'Quick edit' links for blocks
    // Click "Edit" button in toolbar to force Contextual Edit which starts
    // Settings Tray edit mode also.
    data.$el.find(blockConfigureSelector)
      .on('click.outsidein', function () {
        if (!isInEditMode()) {
          $(toggleEditSelector).trigger('click.outsidein');
        }
      });
  });

  /**
   * Gets all items that should be toggled with class during edit mode.
   *
   * @return {jQuery}
   *   Items that should be toggled.
   */
  function getItemsToToggle() {
    return $(itemsToToggleSelector).not(contextualItemsSelector);
  }

  /**
   * Helper to check the state of the outside-in mode.
   *
   * @todo don't use a class for this.
   *
   * @return {boolean}
   *  State of the outside-in edit mode.
   */
  function isInEditMode() {
    return $('#toolbar-bar').hasClass('js-outside-in-edit-mode');
  }

  /**
   * Helper to toggle Edit mode.
   */
  function toggleEditMode() {
    setEditModeState(!isInEditMode());
  }

  /**
   * Prevent default click events except contextual links.
   *
   * In edit mode the default action of click events is suppressed.
   *
   * @param {jQuery.Event} event
   *   The click event.
   */
  function preventClick(event) {
    // Do not prevent contextual links.
    if ($(event.target).closest('.contextual-links').length) {
      return;
    }
    event.preventDefault();
  }

  /**
   *  Helper to switch edit mode state.
   *
   * @param {boolean} editMode
   *  True enable edit mode, false disable edit mode.
   */
  function setEditModeState(editMode) {
    editMode = !!editMode;
    var $editButton = $(toggleEditSelector);
    var $editables;
    // Turn on edit mode.
    if (editMode) {
      $editButton.text(Drupal.t('Editing'));
      // Close the Manage tray if open when entering edit mode.
      if ($('#toolbar-item-administration-tray').hasClass('is-active')) {
        $('#toolbar-item-administration').trigger('click');
      }

      $editables = $('[data-drupal-outsidein="editable"]').once('outsidein');
      if ($editables.length) {
        // Use event capture to prevent clicks on links.
        document.querySelector('#main-canvas').addEventListener('click', preventClick, true);

        // When a click occurs try and find the outside-in edit link
        // and click it.
        $editables
          .not(contextualItemsSelector)
          .on('click.outsidein', function (e) {
            // Contextual links are allowed to function in Edit mode.
            if ($(e.target).closest('.contextual').length || !localStorage.getItem('Drupal.contextualToolbar.isViewing')) {
              return;
            }

            $(e.currentTarget).find(blockConfigureSelector).trigger('click');
          });
      }
    }
    // Disable edit mode.
    else {
      $editables = $('[data-drupal-outsidein="editable"]').removeOnce('outsidein');
      if ($editables.length) {
        document.querySelector('#main-canvas').removeEventListener('click', preventClick, true);
        $editables.off('.outsidein');
      }

      $editButton.text(Drupal.t('Edit'));
      // Close/remove offcanvas.
      $('.ui-dialog-offcanvas .ui-dialog-titlebar-close').trigger('click');
    }
    getItemsToToggle().toggleClass('js-outside-in-edit-mode', editMode);
    $('.edit-mode-inactive').toggleClass('visually-hidden', editMode);
  }

  /**
   * Attaches contextual's edit toolbar tab behavior.
   *
   * @type {Drupal~behavior}
   *
   * @prop {Drupal~behaviorAttach} attach
   *   Attaches contextual toolbar behavior on a contextualToolbar-init event.
   */
  Drupal.behaviors.outsideInEdit = {
    attach: function () {
      var editMode = localStorage.getItem('Drupal.contextualToolbar.isViewing') === 'false';
      if (editMode) {
        setEditModeState(true);
      }
    }
  };

  /**
   * Toggle the js-outside-edit-mode class on items that we want to disable while in edit mode.
   *
   * @type {Drupal~behavior}
   *
   * @prop {Drupal~behaviorAttach} attach
   *   Toggle the js-outside-edit-mode class.
   */
  Drupal.behaviors.toggleEditMode = {
    attach: function () {

      $(toggleEditSelector).once('outsidein').on('click.outsidein', toggleEditMode);

      var search = Drupal.ajax.WRAPPER_FORMAT + '=drupal_dialog';
      var replace = Drupal.ajax.WRAPPER_FORMAT + '=drupal_dialog_offcanvas';
      // Loop through all Ajax links and change the format to offcanvas when
      // needed.
      Drupal.ajax.instances
        .filter(function (instance) {
          var hasElement = instance && !!instance.element;
          var rendererOffcanvas = false;
          var wrapperOffcanvas = false;
          if (hasElement) {
            rendererOffcanvas = $(instance.element).attr('data-dialog-renderer') === 'offcanvas';
            wrapperOffcanvas = instance.options.url.indexOf('drupal_dialog_offcanvas') === -1;
          }
          return hasElement && rendererOffcanvas && wrapperOffcanvas;
        })
        .forEach(function (instance) {
          // @todo Move logic for data-dialog-renderer attribute into ajax.js
          //   https://www.drupal.org/node/2784443
          instance.options.url = instance.options.url.replace(search, replace);
          // Check to make sure existing dialogOptions aren't overridden.
          if (!('dialogOptions' in instance.options.data)) {
            instance.options.data.dialogOptions = {};
          }
          instance.options.data.dialogOptions.outsideInActiveEditableId = $(instance.element).parents('.outside-in-editable').attr('id');
          instance.progress = {type: 'fullscreen'};
        });
    }
  };

  // Manage Active editable class on opening and closing of the dialog.
  $(window).on({
    'dialog:beforecreate': function (event, dialog, $element, settings) {
      if ($element.is('#drupal-offcanvas')) {
        $('body .outside-in-active-editable').removeClass('outside-in-active-editable');
        var $activeElement = $('#' + settings.outsideInActiveEditableId);
        if ($activeElement) {
          $activeElement.addClass('outside-in-active-editable');
        }
      }
    },
    'dialog:beforeclose': function (event, dialog, $element) {
      if ($element.is('#drupal-offcanvas')) {
        $('body .outside-in-active-editable').removeClass('outside-in-active-editable');
      }
    }
  });

})(jQuery, Drupal);


text:
package org.spongepowered.api.data.manipulator;

import org.spongepowered.api.data.DataHolder;
import org.spongepowered.api.data.ImmutableDataHolder;
import org.spongepowered.api.util.persistence.DataBuilder;

import java.util.Optional;

public interface ImmutableDataManipulatorBuilder<I extends ImmutableDataManipulator, M extends DataManipulator<M, I>> extends DataBuilder {

    /**
     * Creates a new specific {@link ImmutableDataManipulator} for consumption.
     *
     * @return The newly created immutable data manipulator
     */
    I createImmutable();

    /**
     * Attempts to read data from the given {@link DataHolder} and constructs
     * a new copy of the {@link DataManipulator} as an instance of
     * T.
     *
     *
If the {@link DataHolder} does not contain the necessary information
     * to pre-populate the {@link DataManipulator}, a fresh new
     * {@link DataManipulator} is returned. If the {@link DataManipulator} is
     * incompatible with the {@link DataHolder}, {@link Optional#empty()} is
     * returned.

     *
     * @param dataHolder The {@link DataHolder} to extract data
     * @return A new instance of this {@link DataManipulator} with relevant data
     *     filled from the given {@link DataHolder}, if available
     */
    Optional createFrom(DataHolder dataHolder);

    /**
     * Creates the desired {@link ImmutableDataManipulator} from the provided
     * {@link ImmutableDataHolder}, if it is supported.
     *
     * @param dataHolder The data holder
     * @return The immutable manipulator, if available
     */
    Optional createFrom(ImmutableDataHolder<?> dataHolder);

    @Override
    ImmutableDataManipulatorBuilder reset();
}

redpajama_set_name: RedPajamaGithub


text:
#pragma once

#include <cstdint>
#include <functional>
#include <memory>
#include <string>

#include "envoy/event/dispatcher.h"
#include "envoy/http/access_log.h"
#include "envoy/http/codec.h"
#include "envoy/http/header_map.h"
#include "envoy/router/router.h"
#include "envoy/ssl/connection.h"
#include "envoy/tracing/http_tracer.h"

namespace Envoy {
namespace Http {

/**
 * Return codes for encode/decode headers filter invocations. The connection manager bases further
 * filter invocations on the return code of the previous filter.
 */
enum class FilterHeadersStatus {
  // Continue filter chain iteration.
  Continue,
  // Do not iterate to any of the remaining filters in the chain. Returning
  // FilterDataStatus::Continue from decodeData()/encodeData() or calling
  // continueDecoding()/continueEncoding() MUST be called if continued filter iteration is desired.
  StopIteration
};

/**
 * Return codes for encode/decode data filter invocations. The connection manager bases further
 * filter invocations on the return code of the previous filter.
 */
enum class FilterDataStatus {
  // Continue filter chain iteration. If headers have not yet been sent to the next filter, they
  // will be sent first via decodeHeaders()/encodeHeaders(). If data has previously been buffered,
  // the data in this callback will be added to the buffer before the entirety is sent to the next
  // filter.
  Continue,
  // Do not iterate to any of the remaining filters in the chain, and buffer body data for later
  // dispatching. Returning FilterDataStatus::Continue from decodeData()/encodeData() or calling
  // continueDecoding()/continueEncoding() MUST be called if continued filter iteration is desired.
  StopIterationAndBuffer,
  // Do not iterate to any of the remaining filters in the chain, but do not buffer any of the
  // body data for later dispatching. Returning FilterDataStatus::Continue from
  // decodeData()/encodeData() or calling continueDecoding()/continueEncoding() MUST be called if
  // continued filter iteration is desired.
  StopIterationNoBuffer
};

/**
 * Return codes for encode/decode trailers filter invocations. The connection manager bases further
 * filter invocations on the return code of the previous filter.
 */
enum class FilterTrailersStatus {
  // Continue filter chain iteration.
  Continue,
  // Do not iterate to any of the remaining filters in the chain. Calling
  // continueDecoding()/continueEncoding() MUST be called if continued filter iteration is desired.
  StopIteration
};

/**
 * The stream filter callbacks are passed to all filters to use for writing response data and
 * interacting with the underlying stream in general.
 */
class StreamFilterCallbacks {
public:
  virtual ~StreamFilterCallbacks() {}

  /**
   * @return uint64_t the ID of the originating connection for logging purposes.
   */
  virtual uint64_t connectionId() PURE;

  /**
   * @return Ssl::Connection* the ssl connection.
   */
  virtual Ssl::Connection* ssl() PURE;

  /**
   * @return Event::Dispatcher& the thread local dispatcher for allocating timers, etc.
   */
  virtual Event::Dispatcher& dispatcher() PURE;

  /**
   * Reset the underlying stream.
   */
  virtual void resetStream() PURE;

  /**
   * Returns the route for the current request. The assumption is that the implementation can do
   * caching where applicable to avoid multiple lookups.
   *
   * NOTE: This breaks down a bit if the caller knows it has modified something that would affect
   *       routing (such as the request headers). In practice, we don't do this anywhere currently,
   *       but in the future we might need to provide the ability to clear the cache if a filter
   *       knows that it has modified the headers in a way that would affect routing. In the future
   *       we may also want to allow the filter to override the route entry.
   */
  virtual Router::RouteConstSharedPtr route() PURE;

  /**
   * @return uint64_t the ID of the originating stream for logging purposes.
   */
  virtual uint64_t streamId() PURE;

  /**
   * @return requestInfo for logging purposes. Individual filter may add specific information to be
   * put into the access log.
   */
  virtual AccessLog::RequestInfo& requestInfo() PURE;

  /**
   * @return span context used for tracing purposes. Individual filters may add or modify
   *              information in the span context.
   */
  virtual Tracing::Span& activeSpan() PURE;

  /**
   * @return the trusted downstream address for the connection.
   */
  virtual const std::string& downstreamAddress() PURE;
};

/**
 * Stream decoder filter callbacks add additional callbacks that allow a decoding filter to restart
 * decoding if they decide to hold data (e.g. for buffering or rate limiting).
 */
class StreamDecoderFilterCallbacks : public virtual StreamFilterCallbacks {
public:
  /**
   * Continue iterating through the filter chain with buffered headers and body data. This routine
   * can only be called if the filter has previously returned StopIteration from decodeHeaders()
   * AND either StopIterationAndBuffer or StopIterationNoBuffer from each previous call to
   * decodeData(). The connection manager will dispatch headers and any buffered body data to the
   * next filter in the chain. Further note that if the request is not complete, this filter will
   * still receive decodeData() calls and must return an appropriate status code depending on what
   * the filter needs to do.
   */
  virtual void continueDecoding() PURE;

  /**
   * @return const Buffer::Instance* the currently buffered data as buffered by this filter or
   *         previous ones in the filter chain. May be nullptr if nothing has been buffered yet.
   */
  virtual const Buffer::Instance* decodingBuffer() PURE;

  /**
   * Add buffered body data. This method is used in advanced cases where returning
   * StopIterationAndBuffer from decodeData() is not sufficient.
   *
   * 1) If a headers only request needs to be turned into a request with a body, this method can
   * be called to add body in the decodeHeaders() callback. Subsequent filters will receive
   * decodeHeaders(..., false) followed by decodeData(..., true). This works both in the direct
   * iteration as well as the continuation case.
   *
   * 2) If additional buffered body data needs to be added by a filter before continuation of
   * data to further filters (outside of callback context).
   *
   * 3) If additional data needs to be added in the decodeTrailers() callback, this method can be
   * called in the context of the callback. All further filters will receive decodeData(..., false)
   * followed by decodeTrailers().
   *
   * It is an error to call this method in any other case.
   */
  virtual void addDecodedData(Buffer::Instance& data) PURE;

  /**
   * Called with headers to be encoded, optionally indicating end of stream.
   *
   * The connection manager inspects certain pseudo headers that are not actually sent downstream.
   * - See source/common/http/headers.h
   *
   * @param headers supplies the headers to be encoded.
   * @param end_stream supplies whether this is a header only request/response.
   */
  virtual void encodeHeaders(HeaderMapPtr&& headers, bool end_stream) PURE;

  /**
   * Called with data to be encoded, optionally indicating end of stream.
   * @param data supplies the data to be encoded.
   * @param end_stream supplies whether this is the last data frame.
   */
  virtual void encodeData(Buffer::Instance& data, bool end_stream) PURE;

  /**
   * Called with trailers to be encoded. This implicitly ends the stream.
   * @param trailers supplies the trailers to encode.
   */
  virtual void encodeTrailers(HeaderMapPtr&& trailers) PURE;
};

/**
 * Common base class for both decoder and encoder filters.
 */
class StreamFilterBase {
public:
  virtual ~StreamFilterBase() {}

  /**
   * This routine is called prior to a filter being destroyed. This may happen after normal stream
   * finish (both downstream and upstream) or due to reset. Every filter is responsible for making
   * sure that any async events are cleaned up in the context of this routine. This includes timers,
   * network calls, etc. The reason there is an onDestroy() method vs. doing this type of cleanup
   * in the destructor is due to the deferred deletion model that Envoy uses to avoid stack unwind
   * complications.
   */
  virtual void onDestroy() PURE;
};

/**
 * Stream decoder filter interface.
 */
class StreamDecoderFilter : public StreamFilterBase {
public:
  /**
   * Called with decoded headers, optionally indicating end of stream.
   * @param headers supplies the decoded headers map.
   * @param end_stream supplies whether this is a header only request/response.
   * @return FilterHeadersStatus determines how filter chain iteration proceeds.
   */
  virtual FilterHeadersStatus decodeHeaders(HeaderMap& headers, bool end_stream) PURE;

  /**
   * Called with a decoded data frame.
   * @param data supplies the decoded data.
   * @param end_stream supplies whether this is the last data frame.
   * @return FilterDataStatus determines how filter chain iteration proceeds.
   */
  virtual FilterDataStatus decodeData(Buffer::Instance& data, bool end_stream) PURE;

  /**
   * Called with decoded trailers, implicitly ending the stream.
   * @param trailers supplies the decoded trailers.
   */
  virtual FilterTrailersStatus decodeTrailers(HeaderMap& trailers) PURE;

  /**
   * Called by the filter manager once to initialize the filter decoder callbacks that the
   * filter should use.
   */
  virtual void setDecoderFilterCallbacks(StreamDecoderFilterCallbacks& callbacks) PURE;
};

typedef std::shared_ptr<StreamDecoderFilter> StreamDecoderFilterSharedPtr;

/**
 * Stream encoder filter callbacks add additional callbacks that allow a encoding filter to restart
 * encoding if they decide to hold data (e.g. for buffering or rate limiting).
 */
class StreamEncoderFilterCallbacks : public virtual StreamFilterCallbacks {
public:
  /**
   * Continue iterating through the filter chain with buffered headers and body data. This routine
   * can only be called if the filter has previously returned StopIteration from encodeHeaders() AND
   * either StopIterationAndBuffer or StopIterationNoBuffer from each previous call to encodeData().
   * The connection manager will dispatch headers and any buffered body data to the next filter in
   * the chain. Further note that if the response is not complete, this filter will still receive
   * encodeData() calls and must return an appropriate status code depending on what the filter
   * needs to do.
   */
  virtual void continueEncoding() PURE;

  /**
   * @return const Buffer::Instance* the currently buffered data as buffered by this filter or
   *         previous ones in the filter chain. May be nullptr if nothing has been buffered yet.
   */
  virtual const Buffer::Instance* encodingBuffer() PURE;

  /**
   * Add buffered body data. This method is used in advanced cases where returning
   * StopIterationAndBuffer from encodeData() is not sufficient.
   *
   * 1) If a headers only response needs to be turned into a response with a body, this method can
   * be called to add body in the encodeHeaders() callback. Subsequent filters will receive
   * encodeHeaders(..., false) followed by encodeData(..., true). This works both in the direct
   * iteration as well as the continuation case.
   *
   * 2) If additional buffered body data needs to be added by a filter before continuation of
   * data to further filters (outside of callback context).
   *
   * 3) If additional data needs to be added in the encodeTrailers() callback, this method can be
   * called in the context of the callback. All further filters will receive encodeData(..., false)
   * followed by encodeTrailers().
   *
   * It is an error to call this method in any other case.
   */
  virtual void addEncodedData(Buffer::Instance& data) PURE;
};

/**
 * Stream encoder filter interface.
 */
class StreamEncoderFilter : public StreamFilterBase {
public:
  /**
   * Called with headers to be encoded, optionally indicating end of stream.
   * @param headers supplies the headers to be encoded.
   * @param end_stream supplies whether this is a header only request/response.
   * @return FilterHeadersStatus determines how filter chain iteration proceeds.
   */
  virtual FilterHeadersStatus encodeHeaders(HeaderMap& headers, bool end_stream) PURE;

  /**
   * Called with data to be encoded, optionally indicating end of stream.
   * @param data supplies the data to be encoded.
   * @param end_stream supplies whether this is the last data frame.
   * @return FilterDataStatus determines how filter chain iteration proceeds.
   */
  virtual FilterDataStatus encodeData(Buffer::Instance& data, bool end_stream) PURE;

  /**
   * Called with trailers to be encoded, implicitly ending the stream.
   * @param trailers supplies the trailes to be encoded.
   */
  virtual FilterTrailersStatus encodeTrailers(HeaderMap& trailers) PURE;

  /**
   * Called by the filter manager once to initialize the filter callbacks that the filter should
   * use.
   */
  virtual void setEncoderFilterCallbacks(StreamEncoderFilterCallbacks& callbacks) PURE;
};

typedef std::shared_ptr<StreamEncoderFilter> StreamEncoderFilterSharedPtr;

/**
 * A filter that handles both encoding and decoding.
 */
class StreamFilter : public StreamDecoderFilter, public StreamEncoderFilter {};

typedef std::shared_ptr<StreamFilter> StreamFilterSharedPtr;

/**
 * These callbacks are provided by the connection manager to the factory so that the factory can
 * build the filter chain in an application specific way.
 */
class FilterChainFactoryCallbacks {
public:
  virtual ~FilterChainFactoryCallbacks() {}

  /**
   * Add a decoder filter that is used when reading stream data.
   * @param filter supplies the filter to add.
   */
  virtual void addStreamDecoderFilter(Http::StreamDecoderFilterSharedPtr filter) PURE;

  /**
   * Add an encoder filter that is used when writing stream data.
   * @param filter supplies the filter to add.
   */
  virtual void addStreamEncoderFilter(Http::StreamEncoderFilterSharedPtr filter) PURE;

  /**
   * Add a decoder/encoder filter that is used both when reading and writing stream data.
   * @param filter supplies the filter to add.
   */
  virtual void addStreamFilter(Http::StreamFilterSharedPtr filter) PURE;

  /**
   * Add an access log handler that is called when the stream is destroyed.
   * @param handler supplies the handler to add.
   */
  virtual void addAccessLogHandler(Http::AccessLog::InstanceSharedPtr handler) PURE;
};

/**
 * A FilterChainFactory is used by a connection manager to create an HTTP level filter chain when a
 * new stream is created on the connection (either locally or remotely). Typically it would be
 * implemented by a configuration engine that would install a set of filters that are able to
 * process an application scenario on top of a stream.
 */
class FilterChainFactory {
public:
  virtual ~FilterChainFactory() {}

  /**
   * Called when a new stream is created on the connection.
   * @param callbacks supplies the "sink" that is used for actually creating the filter chain. @see
   *                  FilterChainFactoryCallbacks.
   */
  virtual void createFilterChain(FilterChainFactoryCallbacks& callbacks) PURE;
};

} // Http
} // Envoy


text:
<?xml version="1.0" encoding="utf-8"?>

<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".UI.zhihu.ZhiHuHomeActivity"
    >

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appBarLayout"
        theme="@style/AppTheme.AppBarOverlay"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        >

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_scrollFlags="scroll|enterAlways"

            >

            <ImageView
                android:id="@+id/search"
                android:layout_width="24dp"
                android:layout_height="24dp"
                android:layout_centerVertical="true"
                android:layout_marginLeft="10dp"
                android:src="@drawable/search"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_marginLeft="10dp"
                android:layout_toRightOf="@id/search"
                android:background="@android:color/transparent"
                android:focusable="false"
                android:hint="search"
                android:textSize="16sp"/>

        </RelativeLayout>

    </android.support.design.widget.AppBarLayout>

    <!--用来填充Fragemnt的FrayLayout-->
    <FrameLayout
        android:id="@+id/fl"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"

        >

    </FrameLayout>

    <!--使用RadioGroup来实现tab的切换-->
    <RadioGroup
        android:id="@+id/rg"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:background="@color/bg_tab"
        android:orientation="horizontal"
        app:layout_behavior="@string/behavior_footer"
        >

        <RadioButton
            android:id="@+id/rb_home"
            style="@style/bottom_tab"
            android:drawableTop="@drawable/sel_home"
            android:text="Home"/>

        <RadioButton
            android:id="@+id/rb_course"
            style="@style/bottom_tab"
            android:drawableTop="@drawable/sel_course"
            android:text="course"/>

        <RadioButton
            android:id="@+id/rb_direct_seeding"
            style="@style/bottom_tab"
            android:drawableTop="@drawable/sel_direct_seeding"
            android:text="direct"/>

        <RadioButton
            android:id="@+id/rb_me"
            style="@style/bottom_tab"
            android:drawableTop="@drawable/sel_me"
            android:text="me"/>

    </RadioGroup>

</android.support.design.widget.CoordinatorLayout>


text:
/* $Id$ */

/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/
package org.apache.manifoldcf.crawler.system;

import org.apache.manifoldcf.core.interfaces.*;
import org.apache.manifoldcf.crawler.interfaces.*;
import java.io.*;
import java.util.*;

/** Class which handles reset for cleanup thread pool (of which there's
* typically only one member).  The reset action here
* is to move the status of documents from "???" back to "PURGATORY".
*/
public class DocCleanupResetManager extends ResetManager
{
  public static final String _rcsid = "@(#)$Id$";

  protected final DocumentCleanupQueue ddq;

  /** Constructor. */
  public DocCleanupResetManager(DocumentCleanupQueue ddq, String processID)
  {
    super(processID);
    this.ddq = ddq;
  }

  /** Reset */
  @Override
  protected void performResetLogic(IThreadContext tc, String processID)
    throws ManifoldCFException
  {
    IJobManager jobManager = JobManagerFactory.make(tc);
    jobManager.resetDocCleanupWorkerStatus(processID);
    ddq.clear();
  }

  /** Do the wakeup logic.
  */
  @Override
  protected void performWakeupLogic()
  {
    ddq.reset();
  }

}


text:
var nconf = require('nconf');

nconf.file({
	file: './tests/config.json'
});

module.exports = nconf;


text:
<?php

$app = 'sympal';
$refresh_assets = true;
require_once(dirname(__FILE__).'/../../../../bootstrap/unit.php');

$t = new lime_test(34);

// initialize some asset objects
$sync = new sfSympalAssetSynchronizer($configuration->getEventDispatcher());
$sync->run();

$asset = get_test_asset_object();
$asset2 = get_test_asset_object('screens-sympalphp');

$t->info('1 - Run some basic functions on the asset');
$t->isnt($asset, null, 'An asset object for the "sympal info.txt" asset was found');
$t->is($asset->isImage(), false, '->isImage() returns false');
$t->is($asset->getType(), 'text', '->getType() returns "text"');
$t->is($asset->exists(), true, '->exists() returns true as the file does exist');
$t->is($asset->getTypeFromExtension(), 'text', '->getTypeFromExtension() returns text');
$t->is($asset->getIcon(), '/sfSympalAssetsPlugin/images/icons/txt.png', '->getIcon() returns the txt.png icon');

$t->is($asset->getExtension(), 'txt', '->getExtension() returns .txt');
$t->is($asset->getPath(), sfConfig::get('sf_upload_dir').'/sympal info.txt', '->getPath() returns the correct path');
$t->is($asset->getRelativePath(), '/sympal info.txt', '->getRelativePath() returns the web url for the asset');
$t->is($asset->getRelativePathDirectory(), '', '->getRelativePathDirectory() returns a blank string');
$t->is($asset->getFilePath(), '/sympal info.txt', '->getFilePath() returns /sympal info.txt');

$t->is($asset2->getPath(), sfConfig::get('sf_upload_dir').'/screens/sympalphp.png', '->getPath() returns the correct path');
$t->is($asset2->getRelativePath(), '/screens/sympalphp.png', '->getRelativePath() returns the web url for the asset');
$t->is($asset2->getRelativePathDirectory(), '/screens', '->getRelativePathDirectory() returns "/screens"');
$t->is($asset2->getFilePath(), '/screens/sympalphp.png', '->getFilePath() returns /sympal info.txt');

$t->like($asset2->getUrl(), '/uploads\/screens\/sympalphp\.png/', '->getFilePath() contains /uploads/screens/sympalphp.png');
$t->like($asset2->getUrl(), '/http\:\/\//', '->getFilePath() contains http://');

$t->is($asset->getName(), 'sympal info.txt', '->getName() return "sympal info.txt"');
$t->is($asset2->getSize(), '275', '->getSize() returns 275 for a 274.7kb file');

$doctrineAsset = $asset->getDoctrineAsset();
$t->is($doctrineAsset->name, $asset->getName(), '->getDoctrineAsset() returns the correct asset');

$t->info('  1.1 - Play with the getOriginal() method');
$original = $asset->getOriginal();
$t->is($original->getPath(), $asset->getPathDirectory().'/.originals/'.$asset->getName(), 'An original copy of the file exists in the .originals directory');

$t->info('  1.1.1 Unlink the original asset and see if we can recreate it');
$asset = get_test_asset_object(); // resets the original
$original = $asset->getOriginal(false);
$t->is($original->getPath(), $asset->getPathDirectory().'/.originals/'.$asset->getName(), 'The original copy file exists, so it returns just fine');

unlink($original->getPath());
$asset = get_test_asset_object(); // resets the original
$original = $asset->getOriginal(false);
$t->is($original, null, '->getOriginal() return null if there is no original and you don\'t request to make a new one');

$asset = get_test_asset_object(); // resets the original
$original = $asset->getOriginal();
$t->is($original->getPath(), $asset->getPathDirectory().'/.originals/'.$asset->getName(), 'The original exists since we\'ve requested it to get recreated');

$t->info('2 - Perform a move operation');

$oldPath = $asset2->getPath();
$newPath = sfConfig::get('sf_upload_dir').'/moved/sympalphp.png';
$asset2->move($newPath);

$t->is($asset2->getPath(), $newPath, '->getPath() now returns the new path');
$t->is($asset2->exists(), true, '->exists returns true');
$t->is(file_exists($oldPath), false, 'The old file path does not exist');

$originalPath = dirname($newPath).'/.originals/sympalphp.png';
$t->is($asset2->getOriginal()->getPath(), $originalPath, '->getOriginal() has the correct new path');
$t->is($asset2->getOriginal()->exists(), true, '->getOriginal() exists');
$t->is(file_exists(dirname($oldPath).'/.originals/sympalphp.png'), false, 'The old original file path does not exist');

$t->info('3 - Perform a delete operation');
$oldPath = $asset2->getPath();
$asset2->delete();
$t->is($asset2->exists(), false, '->exists() returns false');
$t->is(file_exists($oldPath), false, 'The old file path does not exist');
$t->is(file_exists(dirname($oldPath).'/.originals/sympal info.txt'), false, 'The old original file path does not exist');

$t->info('4 - Test the render() method');

// a test rendering class
class testRenderer
{
  public function __construct(sfSympalAssetObject $asset, $options)
  {
  }

  public function render()
  {
    return 'rendered';
  }
}

$t->is($asset->render(array('renderer' => 'testRenderer')), 'rendered', 'Passing a "renderer" options uses a different rendering class');

// linked_thumbnail

function get_test_asset_object($slug = 'sympal-info')
{
  // make sure it's free, so we get a fresh object
  $record = Doctrine_Core::getTable('sfSympalAsset')->findOneBySlug($slug);
  $record->free();

  return Doctrine_Core::getTable('sfSympalAsset')->findOneBySlug($slug)->getAssetObject();
}


text:
package org.fest.assertions.data;

import static org.fest.util.Objects.*;
import static org.fest.util.Strings.quote;

import java.util.Map;

/**
 * Understands an entry in a <code>{@link Map}</code>.
 *
 * @author Yvonne Wang
 */
public class MapEntry {

  /** The key corresponding to this entry. */
  public final Object key;

  /** The value corresponding to this entry. */
  public final Object value;

  /**
   * Creates a new map entry.
   * @param key the key of the entry to create.
   * @param value the value of the entry to create.
   * @return the created map entry.
   */
  public static MapEntry entry(Object key, Object value) {
    return new MapEntry(key, value);
  }

  private MapEntry(Object key, Object value) {
    this.key = key;
    this.value = value;
  }

  @Override public boolean equals(Object obj) {
    if (this == obj) return true;
    if (obj == null) return false;
    if (getClass() != obj.getClass()) return false;
    MapEntry other = (MapEntry) obj;
    if (!areEqual(key, other.key)) return false;
    return areEqual(value, other.value);
  }

  @Override public int hashCode() {
    int result = 1;
    result = HASH_CODE_PRIME * result + hashCodeFor(key);
    result = HASH_CODE_PRIME * result + hashCodeFor(value);
    return result;
  }

  @Override public String toString() {
    return String.format("%s[key=%s, value=%s]", getClass().getSimpleName(), quote(key), quote(value));
  }
}


text:
'''
Created on May 6, 2017

This file is subject to the terms and conditions defined in the
file 'LICENSE.txt', which is part of this source code package.

@author: David Moss
'''

from devices.device import Device

class LightDevice(Device):
    """Lighting Device"""

    # Measurement Names
    MEASUREMENT_NAME_STATUS = 'state'
    MEASUREMENT_NAME_BRIGHTNESS = 'currentLevel'
    MEASUREMENT_NAME_HUE = 'hue'
    MEASUREMENT_NAME_SATURATION = 'saturation'

    MEASUREMENT_PARAMETERS_LIST = [
        MEASUREMENT_NAME_STATUS,
        MEASUREMENT_NAME_BRIGHTNESS,
        MEASUREMENT_NAME_HUE,
        MEASUREMENT_NAME_SATURATION
    ]

    # Command Names
    COMMAND_NAME_STATUS = 'state'
    COMMAND_NAME_BRIGHTNESS = 'currentLevel'

    # Lighting goals
    GOAL_LIGHT_SAVE_ENERGY = 60
    GOAL_LIGHT_LEAVE_LIGHTS_ON_FOR_PETS = 61
    GOAL_LIGHT_SECURITY = 62
    GOAL_LIGHT_OUTDOOR_SECURITY = 64

    # List of Device Types this class is compatible with
    DEVICE_TYPES = [10036, 10071]

    def __init__(self, botengine, device_id, device_type, device_description, precache_measurements=True):
        Device.__init__(self, botengine, device_id, device_type, device_description, precache_measurements=precache_measurements)

        # The boolean on/off state of this device that was saved
        self.saved_state = False

        # Saved brightess
        self.saved_brightness = None

        # Saved hue
        self.saved_hue = None

        # Saved saturation
        self.saved_saturation = None

        # Whether the saved_state is valid or not
        self.saved = False

    def initialize(self, botengine):
        Device.initialize(self, botengine)

        if not hasattr(self, 'saved_brightness'):
            self.saved_brightness = None

        if not hasattr(self, 'saved_hue'):
            self.saved_hue = None

        if not hasattr(self, 'saved_saturation'):
            self.saved_saturation = None

    #===========================================================================
    # Attributes
    #===========================================================================
    def get_device_type_name(self):
        """
        :return: the name of this device type in the given language, for example, "Entry Sensor"
        """
        # NOTE: Device type name
        return _("Light")

    def get_icon(self):
        """
        :return: the font icon name of this device type
        """
        return "lightbulb"

    def get_icon_font(self):
        """
        Get the icon font package from which to render an icon
        :return: The name of the icon font package
        """
        import utilities.utilities as utilities
        return utilities.ICON_FONT_FONTAWESOME_REGULAR

    def is_command(self, measurement_name):
        """
        :param measurement_name: Name of a local measurement name
        :return: True if the given parameter name is a command
        """
        return measurement_name == LightDevice.COMMAND_NAME_STATUS

    def is_light(self):
        """
        :return: True if this is a light
        """
        return True

    def can_control_brightness(self, botengine=None):
        """
        :param botengine: BotEngine environment
        :return: True if we can control brightness on this device
        """
        return self.MEASUREMENT_NAME_BRIGHTNESS in self.measurements

    def can_control_color(self, botengine=None):
        """
        :param botengine: BotEngine environment
        :return: True if we can control brightness on this device
        """
        return self.MEASUREMENT_NAME_HUE in self.measurements and self.MEASUREMENT_NAME_SATURATION in self.measurements

    def current_brightness(self, botengine=None):
        """
        :param botengine: BotEngine environment
        :return: True if we can control brightness on this device
        """
        if self.MEASUREMENT_NAME_BRIGHTNESS in self.measurements:
            # Brightness here is available from the server in units of %
            return self.measurements[self.MEASUREMENT_NAME_BRIGHTNESS][0][0]

        return 100

    def current_hue(self, botengine=None):
        """
        :param botengine: BotEngine environment
        :return: The current hue. None if this parameter doesn't exist.
        """
        if self.MEASUREMENT_NAME_HUE in self.measurements:
            return self.measurements[self.MEASUREMENT_NAME_HUE][0][0]

        return None

    def current_saturation(self, botengine=None):
        """
        :param botengine:
        :return: The current saturation. None if the parameter doesn't exist
        """
        if self.MEASUREMENT_NAME_SATURATION in self.measurements:
            return self.measurements[self.MEASUREMENT_NAME_SATURATION][0][0]

        return None

    def is_on(self, botengine=None):
        """
        :param botengine: BotEngine environment
        :return: True if this light is on
        """
        if self.MEASUREMENT_NAME_STATUS in self.measurements:
            return self.measurements[self.MEASUREMENT_NAME_STATUS][0][0]

        return False

    def is_off(self, botengine=None):
        """
        :param botengine: BotEngine environment
        :return: True if this light is on
        """
        if self.MEASUREMENT_NAME_STATUS in self.measurements:
            return self.measurements[self.MEASUREMENT_NAME_STATUS][0][0] == False

        return False

    def did_turn_on(self, botengine=None):
        """
        Did the light just turn on in the last execution
        :param botengine: BotEngine environment
        :return: True if the light turned on in the last execution
        """
        if self.MEASUREMENT_NAME_STATUS in self.measurements:
            if self.MEASUREMENT_NAME_STATUS in self.last_updated_params:
                return self.measurements[self.MEASUREMENT_NAME_STATUS][0][0] == True

        return False

    def did_turn_off(self, botengine=None):
        """
        Did the light just turn off in the last execution
        :param botengine: BotEngine environment
        :return: True if the light turned off in the last execution
        """
        if self.MEASUREMENT_NAME_STATUS in self.measurements:
            if self.MEASUREMENT_NAME_STATUS in self.last_updated_params:
                return self.measurements[self.MEASUREMENT_NAME_STATUS][0][0] == False

        return False

    #===========================================================================
    # Commands
    #===========================================================================
    def save(self, botengine):
        """Save the status of this device"""
        if not self.is_connected or not self.can_control:
            return False

        try:
            self.saved_state = self.measurements[self.MEASUREMENT_NAME_STATUS][0][0]
        except:
            self.saved_state = False

        self.saved_brightness = self.current_brightness(botengine)
        self.saved_hue = self.current_hue(botengine)
        self.saved_saturation = self.current_saturation(botengine)
        self.saved = True
        return True

    def restore(self, botengine):
        """
        Restore the status of the device from the save point
        :return: True if the lights were restored, False if there was nothing to restore
        """
        if not self.is_connected or not self.can_control:
            return False

        if not self.saved:
            return False

        self.saved = False

        if self.saved_state:
            self.on(botengine)
        else:
            self.off(botengine)

        # TODO : The DSR gateway does not support multiple parameters in a single command
        # Really this should be handled underneath this application layer, by the JEXL abstraction layer in the cloud.
        if self.saved_saturation:
            #self.set_saturation(botengine, self.saved_saturation)
            self.saved_saturation = None

        if self.saved_brightness:
            #self.set_brightness(botengine, self.saved_brightness)
            self.saved_brightness = None

        if self.saved_hue:
            #self.set_hue(botengine, self.saved_hue)
            self.saved_hue = None

        return True

    def toggle(self, botengine):
        """
        Toggle the light on or off
        :param botengine:
        :return:
        """
        if self.is_on(botengine):
            self.off(botengine)
        else:
            self.on(botengine)

    def on(self, botengine):
        """
        Turn on
        :param botengine: BotEngine environment
        :return: True if the command will attempt to be delivered
        """
        if not self.is_connected or not self.can_control:
            return False

        botengine.get_logger().info("Switch ON " + str(self.description))

        # Turning on and off requires 2 commands
        commands = [
            botengine.form_command(self.COMMAND_NAME_STATUS, True)  # This does accept True
        ]

        botengine.send_commands(self.device_id, commands)

        # We cannot send brightness and on/off commands in the same command on some gateways.
        botengine.flush_commands()

        return True

    def off(self, botengine):
        """
        Turn off
        :param botengine: BotEngine environment
        :return: True if the command will attempt to be delivered
        """
        if not self.is_connected or not self.can_control:
            return False

        botengine.get_logger().info("Switch OFF " + str(self.description))

        # Turning on and off requires 2 commands
        commands = [
            botengine.form_command(self.COMMAND_NAME_STATUS, False)   # TODO this should accept False but does not
        ]

        botengine.send_commands(self.device_id, commands)
        return True

    def set_brightness(self, botengine, percent):
        """
        Set the brightness level between 0 - 100%
        :param botengine: BotEngine environment
        :param percent: 0-100% brightness
        :return: True if the command will attempt to be delivered
        """
        if not self.is_connected or not self.can_control:
            return False

        botengine.get_logger().info("Set brightness of " + str(self.description) + " to " + str(percent) + "%")

        # Adjusting the brightness requires 2 parameters for compatibility with our partners gateways
        commands = [
            botengine.form_command("currentLevel", int((percent / 100.0) * 254)),
            botengine.form_command("commandName", "setLevel")
        ]

        botengine.send_commands(self.device_id, commands)

        # We cannot send brightness and on/off commands in the same command on some gateways.
        botengine.flush_commands()

    def set_saturation(self, botengine, saturation):
        """
        Set the saturation of the light. 254 is most saturated (colored) and 0 is the least saturated (white)
        :param botengine: BotEngine environment
        :param saturation: Saturation between 0 - 254
        :return:
        """
        if saturation < 0:
            saturation = 0

        elif saturation > 254:
            saturation = 254

        if self.MEASUREMENT_NAME_SATURATION in self.measurements:
            botengine.send_command(self.device_id, self.MEASUREMENT_NAME_SATURATION, saturation)

    def set_hue(self, botengine, hue):
        """
        Hue of the light. This is a wrapping value between 0 - 65535.
        Note that hue and saturation values are hardware dependent which means that programming two devices with the same value does not guarantee they will be the same color.
        Values 0 and 65535 would mean the light will resemble the color red.
        Value 21845 for green
        Value 43690 for blue

        :param botengine:
        :param hue: Hue of the light between 0 - 65535 (wrapping color spectrum, 0 is about equal to 65535 which is red)
        :return:
        """
        if hue < 0:
            hue = 0

        elif hue > 65535:
            hue = 65535

        if self.MEASUREMENT_NAME_HUE in self.measurements:
            botengine.send_command(self.device_id, self.MEASUREMENT_NAME_HUE, hue)

    def set_red(self, botengine):
        """
        Set the color to red. This does not control brightness or on/off state.
        :param botengine:
        :return:
        """
        self.set_saturation(botengine, 254)
        self.set_hue(botengine, 0)

    def set_green(self, botengine):
        """
        Set the color to green. This does not control brightness or on/off state.
        :param botengine:
        :return:
        """
        self.set_saturation(botengine, 254)
        self.set_hue(botengine, 21845)

    def set_blue(self, botengine):
        """
        Set the color to blue. This does not control brightness or on/off state.
        :param botengine:
        :return:
        """
        self.set_saturation(botengine, 254)
        self.set_hue(botengine, 43690)


text:
(function() {
	f = document.createElement('iframe');
	f.src = document.getElementById('header-v6a8oxpf48xfzy0rhjra').getAttribute('data-file');
	f.border = 0;
	f.id = 'header-frame-6jk3h6a234g2a3';
	var fs = f.style;
	fs.position = 'absolute';
	fs.overflow = 'hidden';
	fs.width = '1000px';
	fs.top = 0;
	fs.left = 0;
	fs.zIndex = 100003;
	fs.border = 'none';
	fs.padding = 0;
	fs.margin = 0;

	document.body.insertBefore(f, document.body.firstChild);

	var oldVal = parseInt(document.getElementsByTagName('html')[0].style.paddingTop) || 0;

	window.addEventListener('message', function(event) {
		document.getElementById('header-frame-6jk3h6a234g2a3').height = event.data;
		document.getElementsByTagName('html')[0].style.paddingTop = (oldVal + event.data) + 'px';

		// TODO push down all position absolute elements and remeber their old positions
//		var all = document.querySelector('*');
//		for(var i = 0; i < all.length; i++) {
//		  if (all[i].style.position == 'absolute' && all[i] !== f) {
//		    all[i].style.top = ((parseInt(all[i].style.top) || 0) + event.data) + 'px';
//		  }
//		}
	});
})();


text: Specify an url to attack (e.g. "http://localhost:8180/bodgeit/").


text:
package org.yx.redis;

import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.yx.exception.SumkException;
import org.yx.util.StringUtil;

@SuppressWarnings("rawtypes")
public class RedisConfig extends GenericObjectPoolConfig {

	private final String hosts;
	private int db = 0;
	private int connectionTimeout = 5000;
	private int timeout = 2000;
	private String user;

	public String getUser() {
		return user;
	}

	public void setUser(String user) {
		this.user = user;
	}

	private String password;
	private int maxAttempts = 3;
	private String master;
	private String alias;

	/**
	 * 1 cluster 2 sentinel 其它是普通
	 */
	private String type;

	@SuppressWarnings("deprecation")
	public RedisConfig(String host) {
		if (host == null || host.isEmpty()) {
			throw new SumkException(657645465, "redis host cannot be empty");
		}
		this.hosts = StringUtil.toLatin(host.trim());

		setTestWhileIdle(true);
		setMinEvictableIdleTimeMillis(60000);
		setTimeBetweenEvictionRunsMillis(30000);
	}

	public String getMaster() {
		return master;
	}

	public void setMaster(String master) {
		this.master = master;
	}

	public String hosts() {
		return hosts;
	}

	public int getTimeout() {
		return timeout;
	}

	public void setTimeout(int timeout) {
		this.timeout = timeout;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public int getDb() {
		return db;
	}

	public void setDb(int db) {
		this.db = db;
	}

	public int getMaxAttempts() {
		return maxAttempts;
	}

	public void setMaxAttempts(int maxAttempts) {
		this.maxAttempts = maxAttempts;
	}

	public String getAlias() {
		return alias;
	}

	public void setAlias(String alias) {
		this.alias = alias;
	}

	public int getConnectionTimeout() {
		return connectionTimeout;
	}

	public void setConnectionTimeout(int connectionTimeout) {
		this.connectionTimeout = connectionTimeout;
	}

	@Override
	public String toString() {
		return "hosts=" + hosts + ", db=" + db + ", user=" + user + ", password=" + password + ", timeout=" + timeout
				+ ", maxAttempts=" + maxAttempts + " , " + super.toString();
	}

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}

}


text:
var timeslice = require('./timeslice.js');

(function(){
	// get method alias
	var args = process.argv.slice(2);
	if( args.length == 0 ){
		console.log("usage:");
		console.log("timeslace gp");
		console.log("timeslice rh args");
		process.exit(1);
	}

	if( args[0] == "gp" ){

		timeslice.get_projects();

	} else if( args[0] == "rh" ){

		timeslice.report_hours();

	} else {
		console.log( args[0] + " is not a valid command ");
	}

}).call(this);


text:
import {ActionTool, ActionToolView} from "./action_tool"
import * as p from "core/properties"
import {tool_icon_save} from "styles/icons.css"
import {MenuItem} from "core/util/menus"

export class SaveToolView extends ActionToolView {
  override model: SaveTool

  async copy(): Promise<void> {
    const blob = await this.parent.export().to_blob()
    const item = new ClipboardItem({[blob.type]: blob})
    await navigator.clipboard.write([item])
  }

  async save(name: string): Promise<void> {
    const blob = await this.parent.export().to_blob()
    const link = document.createElement("a")
    link.href = URL.createObjectURL(blob)
    link.download = name // + ".png" | "svg" (inferred from MIME type)
    link.target = "_blank"
    link.dispatchEvent(new MouseEvent("click"))
  }

  doit(action: "save" | "copy" = "save"): void {
    switch (action) {
      case "save": {
        const filename = this.model.filename ?? prompt("Enter filename", "bokeh_plot")
        if (filename != null) {
          this.save(filename)
        }
        break
      }
      case "copy": {
        this.copy()
        break
      }
    }
  }
}

export namespace SaveTool {
  export type Attrs = p.AttrsOf<Props>

  export type Props = ActionTool.Props & {
    filename: p.Property<string | null>
  }
}

export interface SaveTool extends SaveTool.Attrs {}

export class SaveTool extends ActionTool {
  override properties: SaveTool.Props
  override __view_type__: SaveToolView

  constructor(attrs?: Partial<SaveTool.Attrs>) {
    super(attrs)
  }

  static {
    this.prototype.default_view = SaveToolView

    this.define<SaveTool.Props>(({String, Nullable}) => ({
      filename: [ Nullable(String), null ],
    }))

    this.register_alias("save", () => new SaveTool())
  }

  override tool_name = "Save"
  override tool_icon = tool_icon_save

  override get menu(): MenuItem[] | null {
    return [
      {
        icon: "bk-tool-icon-copy",
        tooltip: "Copy image to clipboard",
        if: () => typeof ClipboardItem !== "undefined",
        handler: () => {
          this.do.emit("copy")
        },
      },
    ]
  }
}


text:
package cassandra

// #cgo LDFLAGS: -lcassandra
// #include <stdlib.h>
// #include <cassandra.h>
// #include "cassandra-types.h"
import "C"
import "unsafe"
import "errors"
import "reflect"

const (
	CASS_VALUE_TYPE_UNKNOWN   = 0xFFFF
	CASS_VALUE_TYPE_CUSTOM    = 0x0000
	CASS_VALUE_TYPE_ASCII     = 0x0001
	CASS_VALUE_TYPE_BIGINT    = 0x0002
	CASS_VALUE_TYPE_BLOB      = 0x0003
	CASS_VALUE_TYPE_BOOLEAN   = 0x0004
	CASS_VALUE_TYPE_COUNTER   = 0x0005
	CASS_VALUE_TYPE_DECIMAL   = 0x0006
	CASS_VALUE_TYPE_DOUBLE    = 0x0007
	CASS_VALUE_TYPE_FLOAT     = 0x0008
	CASS_VALUE_TYPE_INT       = 0x0009
	CASS_VALUE_TYPE_TEXT      = 0x000A
	CASS_VALUE_TYPE_TIMESTAMP = 0x000B
	CASS_VALUE_TYPE_UUID      = 0x000C
	CASS_VALUE_TYPE_VARCHAR   = 0x000D
	CASS_VALUE_TYPE_VARINT    = 0x000E
	CASS_VALUE_TYPE_TIMEUUID  = 0x000F
	CASS_VALUE_TYPE_INET      = 0x0010
	CASS_VALUE_TYPE_LIST      = 0x0020
	CASS_VALUE_TYPE_MAP       = 0x0021
	CASS_VALUE_TYPE_SET       = 0x0022
)

type Cluster struct {
	cptr *C.struct_CassCluster_
}

type Future struct {
	cptr *C.struct_CassFuture_
}

type Session struct {
	cptr *C.struct_CassSession_
}

type Result struct {
	iter *C.struct_CassIterator_
	cptr *C.struct_CassResult_
}

type Prepared struct {
	cptr *C.struct_CassPrepared_
}

type Statement struct {
	cptr *C.struct_CassStatement_
}

type Uuid struct {
	cptr *C.struct_CassUuid_
}

func (u Uuid) String() string {
	var str C.CassString
	C.cass_uuid_string(*u.cptr, str.data)
	str.length = C.CASS_UUID_STRING_LENGTH
	return C.GoStringN(str.data, C.int(str.length))
}

type UuidGenerator struct {
	cptr *C.struct_CassUuidGen_
}

func NewCluster() *Cluster {
	cluster := new(Cluster)
	cluster.cptr = C.cass_cluster_new()

	/* Latency-aware routing enabled with the default settings */
	C.cass_cluster_set_latency_aware_routing(cluster.cptr, C.cass_true)

	// defer cluster.Finalize()

	return cluster
}

func NewSession() *Session {
	session := new(Session)
	session.cptr = C.cass_session_new()
	return session
}

func NewStatement(query string, param_count int) *Statement {
	var cass_query C.struct_CassString_
	cass_query.data = C.CString(query)
	cass_query.length = C.size_t(len(query))
	defer C.free(unsafe.Pointer(cass_query.data))

	statement := new(Statement)
	statement.cptr = C.cass_statement_new_n(cass_query.data, cass_query.length, C.size_t(param_count))
	// defer statement.Finalize()
	return statement
}

func NewUuidGenerator() *UuidGenerator {
	generator := new(UuidGenerator)
	generator.cptr = C.cass_uuid_gen_new()
	return generator
}

func NewUuidGeneratorWithNode(node uint64) *UuidGenerator {
	generator := new(UuidGenerator)
	generator.cptr = C.cass_uuid_gen_new_with_node(C.cass_uint64_t(node))
	return generator
}

func (generator *UuidGenerator) NewUuidGenTime() *Uuid {
	uuid := new(Uuid)
	C.cass_uuid_gen_time(generator.cptr, uuid.cptr)
	return uuid
}

func (generator *UuidGenerator) NewUuidGenRandom() *Uuid {
	uuid := new(Uuid)
	C.cass_uuid_gen_random(generator.cptr, uuid.cptr)
	return uuid
}

func (generator *UuidGenerator) NewUuidFromTime(timestamp uint64) *Uuid {
	uuid := new(Uuid)
	C.cass_uuid_gen_from_time(generator.cptr, C.cass_uint64_t(timestamp), uuid.cptr)
	return uuid
}

func (prepared *Prepared) Bind() *Statement {
	statement := new(Statement)
	statement.cptr = C.cass_prepared_bind(prepared.cptr)
	// defer statement.Finalize()
	return statement
}

func (statement *Statement) Bind(args ...interface{}) error {
	var err C.CassError = C.CASS_OK

	for i, v := range args {

		switch v := v.(type) {

		case nil:
			err = C.cass_statement_bind_null(statement.cptr, C.size_t(i))

		case int32:
			err = C.cass_statement_bind_int32(statement.cptr, C.size_t(i), C.cass_int32_t(v))

		case int64:
			err = C.cass_statement_bind_int64(statement.cptr, C.size_t(i), C.cass_int64_t(v))

		case float32:
			err = C.cass_statement_bind_float(statement.cptr, C.size_t(i), C.cass_float_t(v))

		case float64:
			err = C.cass_statement_bind_double(statement.cptr, C.size_t(i), C.cass_double_t(v))

		case bool:
			if v {
				err = C.cass_statement_bind_bool(statement.cptr, C.size_t(i), 1)
			} else {
				err = C.cass_statement_bind_bool(statement.cptr, C.size_t(i), 0)
			}

		case string:
			var str C.CassString
			str.data = C.CString(v)
			str.length = C.size_t(len(v))
			defer C.free(unsafe.Pointer(str.data))
			err = C.cass_statement_bind_string_n(statement.cptr, C.size_t(i), str.data, str.length)

		case []byte:
			var bytes C.CassBytes
			bytes.data = (*C.cass_byte_t)(unsafe.Pointer(&v))
			bytes.size = C.size_t(len(v))
			err = C.cass_statement_bind_bytes(statement.cptr, C.size_t(i), bytes.data, bytes.size)

		case *Uuid:
			C.cass_statement_bind_uuid(statement.cptr, C.size_t(i), *v.cptr)
		}

	}

	if err != C.CASS_OK {
		return errors.New(C.GoString(C.cass_error_desc(err)))
	}

	return nil
}

func (cluster *Cluster) Finalize() {
	C.cass_cluster_free(cluster.cptr)
	cluster.cptr = nil
}

func (session *Session) Finalize() {
	C.cass_session_free(session.cptr)
	session.cptr = nil
}

func (future *Future) Finalize() {
	C.cass_future_free(future.cptr)
	future.cptr = nil
}

func (result *Result) Finalize() {
	C.cass_result_free(result.cptr)
	result.cptr = nil
}

func (prepared *Prepared) Finalize() {
	C.cass_prepared_free(prepared.cptr)
	prepared.cptr = nil
}

func (statement *Statement) Finalize() {
	C.cass_statement_free(statement.cptr)
	statement.cptr = nil
}

func (generator *UuidGenerator) Finalize() {
	C.cass_uuid_gen_free(generator.cptr)
	generator.cptr = nil
}

func (future *Future) Result() *Result {
	result := new(Result)
	result.cptr = C.cass_future_get_result(future.cptr)
	// defer result.Finalize()
	return result
}

func (future *Future) Prepared() *Prepared {
	prepared := new(Prepared)
	prepared.cptr = C.cass_future_get_prepared(future.cptr)
	// defer prepared.Finalize()
	return prepared
}

func (future *Future) Ready() bool {
	return C.cass_future_ready(future.cptr) == C.cass_true
}

func (future *Future) Wait() {
	C.cass_future_wait(future.cptr)
}

func (future *Future) WaitTimed(timeout uint64) bool {
	return C.cass_future_wait_timed(future.cptr, C.cass_duration_t(timeout)) == C.cass_true
}

func (cluster *Cluster) SetContactPoints(contactPoints string) {
	contacts_cstr := C.CString(contactPoints)
	defer C.free(unsafe.Pointer(contacts_cstr))
	C.cass_cluster_set_contact_points(cluster.cptr, contacts_cstr)
}

func (cluster *Cluster) SetPort(port int64) {
	port_cint := C.int(port)
	C.cass_cluster_set_port(cluster.cptr, port_cint)
}

func (cluster *Cluster) SessionConnect(session *Session) *Future {
	future := new(Future)
	future.cptr = C.cass_session_connect(session.cptr, cluster.cptr)
	return future
}

func (session *Session) Execute(statement *Statement) *Future {
	future := new(Future)
	future.cptr = C.cass_session_execute(session.cptr, statement.cptr)
	return future
}

func (result *Result) RowCount() uint64 {
	return uint64(C.cass_result_row_count(result.cptr))
}

func (result *Result) ColumnCount() uint64 {
	return uint64(C.cass_result_column_count(result.cptr))
}

func (result *Result) ColumnName(index uint64) string {
	var column_name C.CassString
	C.cass_result_column_name(result.cptr, C.size_t(index), &(column_name.data), &(column_name.length))
	return C.GoStringN(column_name.data, C.int(column_name.length))
}

func (result *Result) ColumnType(index uint64) int {
	return int(C.cass_result_column_type(result.cptr, C.size_t(index)))
}

func (result *Result) HasMorePages() bool {
	return C.cass_result_has_more_pages(result.cptr) != 0
}

func (result *Result) Next() bool {
	if result.iter == nil {
		result.iter = C.cass_iterator_from_result(result.cptr)
	}
	return C.cass_iterator_next(result.iter) != 0
}

func (result *Result) Scan(args ...interface{}) error {

	if result.ColumnCount() != uint64(len(args)) {
		errors.New("invalid argument count")
	}

	row := C.cass_iterator_get_row(result.iter)

	var err C.CassError = C.CASS_OK

	for i, v := range args {
		value := C.cass_row_get_column(row, C.size_t(i))

		switch v := v.(type) {

		case *string:
			var str C.CassString
			err = C.cass_value_get_string(value, &str.data, &str.length)
			if err != C.CASS_OK {
				return errors.New(C.GoString(C.cass_error_desc(err)))
			}
			*v = C.GoStringN(str.data, C.int(str.length))

		case *[]byte:
			var b C.CassBytes
			err = C.cass_value_get_bytes(value, &b.data, &b.size)
			if err != C.CASS_OK {
				return errors.New(C.GoString(C.cass_error_desc(err)))
			}
			*v = C.GoBytes(unsafe.Pointer(b.data), C.int(b.size))

		case *int32:
			var i32 C.cass_int32_t
			err = C.cass_value_get_int32(value, &i32)
			if err != C.CASS_OK {
				return errors.New(C.GoString(C.cass_error_desc(err)))
			}
			*v = int32(i32)

		case *int64:
			var i64 C.cass_int64_t
			err = C.cass_value_get_int64(value, &i64)
			if err != C.CASS_OK {
				return errors.New(C.GoString(C.cass_error_desc(err)))
			}
			*v = int64(i64)

		case *float32:
			var f32 C.cass_float_t
			err = C.cass_value_get_float(value, &f32)
			if err != C.CASS_OK {
				return errors.New(C.GoString(C.cass_error_desc(err)))
			}
			*v = float32(f32)

		case *float64:
			var f64 C.cass_double_t
			err = C.cass_value_get_double(value, &f64)
			if err != C.CASS_OK {
				return errors.New(C.GoString(C.cass_error_desc(err)))
			}
			*v = float64(f64)

		case *bool:
			var b C.cass_bool_t
			err = C.cass_value_get_bool(value, &b)
			if err != C.CASS_OK {
				return errors.New(C.GoString(C.cass_error_desc(err)))
			}
			*v = bool(b != 0)

		default:
			return errors.New("unsupported type in Scan: " + reflect.TypeOf(v).String())
		}
	}

	return nil
}


text:
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
using static Microsoft.CodeAnalysis.CodeActions.CodeAction;
using CodeFixGroupKey = System.Tuple<Microsoft.CodeAnalysis.Diagnostics.DiagnosticData, Microsoft.CodeAnalysis.CodeActions.CodeActionPriority, Microsoft.CodeAnalysis.CodeActions.CodeActionPriority?>;

namespace Microsoft.CodeAnalysis.UnifiedSuggestions
{
    /// <summary>
    /// Provides mutual code action logic for both local and LSP scenarios
    /// via intermediate interface <see cref="IUnifiedSuggestedAction"/>.
    /// </summary>
    internal class UnifiedSuggestedActionsSource
    {
        /// <summary>
        /// Gets, filters, and orders code fixes.
        /// </summary>
        public static async ValueTask<ImmutableArray<UnifiedSuggestedActionSet>> GetFilterAndOrderCodeFixesAsync(
            Workspace workspace,
            ICodeFixService codeFixService,
            Document document,
            TextSpan selection,
            bool isBlocking,
            Func<string, IDisposable?> addOperationScope,
            CancellationToken cancellationToken)
        {
            // Intentionally switch to a threadpool thread to compute fixes.  We do not want to accidentally
            // run any of this on the UI thread and potentially allow any code to take a dependency on that.
            var fixes = await Task.Run(() => codeFixService.GetFixesAsync(
                document, selection, includeSuppressionFixes: true, isBlocking, addOperationScope, cancellationToken), cancellationToken).ConfigureAwait(false);

            var filteredFixes = fixes.WhereAsArray(c => c.Fixes.Length > 0);
            var organizedFixes = OrganizeFixes(workspace, filteredFixes);

            return organizedFixes;
        }

        /// <summary>
        /// Arrange fixes into groups based on the issue (diagnostic being fixed) and prioritize these groups.
        /// </summary>
        private static ImmutableArray<UnifiedSuggestedActionSet> OrganizeFixes(
            Workspace workspace,
            ImmutableArray<CodeFixCollection> fixCollections)
        {
            var map = ImmutableDictionary.CreateBuilder<CodeFixGroupKey, IList<UnifiedSuggestedAction>>();
            using var _ = ArrayBuilder<CodeFixGroupKey>.GetInstance(out var order);

            // First group fixes by diagnostic and priority.
            GroupFixes(workspace, fixCollections, map, order);

            // Then prioritize between the groups.
            var prioritizedFixes = PrioritizeFixGroups(map.ToImmutable(), order.ToImmutable(), workspace);
            return prioritizedFixes;
        }

        /// <summary>
        /// Groups fixes by the diagnostic being addressed by each fix.
        /// </summary>
        private static void GroupFixes(
           Workspace workspace,
           ImmutableArray<CodeFixCollection> fixCollections,
           IDictionary<CodeFixGroupKey, IList<UnifiedSuggestedAction>> map,
           ArrayBuilder<CodeFixGroupKey> order)
        {
            foreach (var fixCollection in fixCollections)
                ProcessFixCollection(workspace, map, order, fixCollection);
        }

        private static void ProcessFixCollection(
            Workspace workspace,
            IDictionary<CodeFixGroupKey, IList<UnifiedSuggestedAction>> map,
            ArrayBuilder<CodeFixGroupKey> order,
            CodeFixCollection fixCollection)
        {
            var fixes = fixCollection.Fixes;
            var fixCount = fixes.Length;

            var nonSupressionCodeFixes = fixes.WhereAsArray(f => !IsTopLevelSuppressionAction(f.Action));
            var supressionCodeFixes = fixes.WhereAsArray(f => IsTopLevelSuppressionAction(f.Action));

            AddCodeActions(workspace, map, order, fixCollection,
                GetFixAllSuggestedActionSet, nonSupressionCodeFixes);

            // Add suppression fixes to the end of a given SuggestedActionSet so that they
            // always show up last in a group.
            AddCodeActions(workspace, map, order, fixCollection,
                GetFixAllSuggestedActionSet, supressionCodeFixes);

            return;

            // Local functions
            UnifiedSuggestedActionSet? GetFixAllSuggestedActionSet(CodeAction codeAction)
                => GetUnifiedFixAllSuggestedActionSet(
                    codeAction, fixCount, fixCollection.FixAllState,
                    fixCollection.SupportedScopes, fixCollection.FirstDiagnostic,
                    workspace);
        }

        private static void AddCodeActions(
            Workspace workspace, IDictionary<CodeFixGroupKey, IList<UnifiedSuggestedAction>> map,
            ArrayBuilder<CodeFixGroupKey> order, CodeFixCollection fixCollection,
            Func<CodeAction, UnifiedSuggestedActionSet?> getFixAllSuggestedActionSet,
            ImmutableArray<CodeFix> codeFixes)
        {
            foreach (var fix in codeFixes)
            {
                var unifiedSuggestedAction = GetUnifiedSuggestedAction(fix.Action, fix);
                AddFix(fix, unifiedSuggestedAction, map, order);
            }

            return;

            // Local functions
            UnifiedSuggestedAction GetUnifiedSuggestedAction(CodeAction action, CodeFix fix)
            {
                if (action.NestedCodeActions.Length > 0)
                {
                    var nestedActions = action.NestedCodeActions.SelectAsArray(
                        nestedAction => GetUnifiedSuggestedAction(nestedAction, fix));

                    var set = new UnifiedSuggestedActionSet(
                        categoryName: null,
                        actions: nestedActions,
                        title: null,
                        priority: GetUnifiedSuggestedActionSetPriority(action.Priority),
                        applicableToSpan: fix.PrimaryDiagnostic.Location.SourceSpan);

                    return new UnifiedSuggestedActionWithNestedActions(
                        workspace, action, action.Priority, fixCollection.Provider, ImmutableArray.Create(set));
                }
                else
                {
                    return new UnifiedCodeFixSuggestedAction(
                        workspace, action, action.Priority, fix, fixCollection.Provider,
                        getFixAllSuggestedActionSet(action));
                }
            }
        }

        private static void AddFix(
            CodeFix fix, UnifiedSuggestedAction suggestedAction,
            IDictionary<CodeFixGroupKey, IList<UnifiedSuggestedAction>> map,
            ArrayBuilder<CodeFixGroupKey> order)
        {
            var groupKey = GetGroupKey(fix);
            if (!map.ContainsKey(groupKey))
            {
                order.Add(groupKey);
                map[groupKey] = ImmutableArray.CreateBuilder<UnifiedSuggestedAction>();
            }

            map[groupKey].Add(suggestedAction);
            return;

            static CodeFixGroupKey GetGroupKey(CodeFix fix)
            {
                var diag = fix.GetPrimaryDiagnosticData();
                if (fix.Action is AbstractConfigurationActionWithNestedActions configurationAction)
                {
                    return new CodeFixGroupKey(
                        diag, configurationAction.Priority, configurationAction.AdditionalPriority);
                }

                return new CodeFixGroupKey(diag, fix.Action.Priority, null);
            }
        }

        // If the provided fix all context is non-null and the context's code action Id matches
        // the given code action's Id, returns the set of fix all occurrences actions associated
        // with the code action.
        private static UnifiedSuggestedActionSet? GetUnifiedFixAllSuggestedActionSet(
            CodeAction action,
            int actionCount,
            FixAllState fixAllState,
            ImmutableArray<FixAllScope> supportedScopes,
            Diagnostic firstDiagnostic,
            Workspace workspace)
        {

            if (fixAllState == null)
            {
                return null;
            }

            if (actionCount > 1 && action.EquivalenceKey == null)
            {
                return null;
            }

            using var fixAllSuggestedActionsDisposer = ArrayBuilder<UnifiedFixAllSuggestedAction>.GetInstance(
                out var fixAllSuggestedActions);
            foreach (var scope in supportedScopes)
            {
                var fixAllStateForScope = fixAllState.With(scope: scope, codeActionEquivalenceKey: action.EquivalenceKey);
                var fixAllSuggestedAction = new UnifiedFixAllSuggestedAction(
                    workspace, action, action.Priority, fixAllStateForScope, firstDiagnostic);

                fixAllSuggestedActions.Add(fixAllSuggestedAction);
            }

            return new UnifiedSuggestedActionSet(
                categoryName: null,
                actions: fixAllSuggestedActions.ToImmutable(),
                title: CodeFixesResources.Fix_all_occurrences_in,
                priority: UnifiedSuggestedActionSetPriority.Lowest,
                applicableToSpan: null);
        }

        /// <summary>
        /// Return prioritized set of fix groups such that fix group for suppression always show up at the bottom of the list.
        /// </summary>
        /// <remarks>
        /// Fix groups are returned in priority order determined based on <see cref="ExtensionOrderAttribute"/>.
        /// Priority for all <see cref="UnifiedSuggestedActionSet"/>s containing fixes is set to
        /// <see cref="UnifiedSuggestedActionSetPriority.Medium"/> by default.
        /// The only exception is the case where a <see cref="UnifiedSuggestedActionSet"/> only contains suppression fixes -
        /// the priority of such <see cref="UnifiedSuggestedActionSet"/>s is set to
        /// <see cref="UnifiedSuggestedActionSetPriority.Lowest"/> so that suppression fixes
        /// always show up last after all other fixes (and refactorings) for the selected line of code.
        /// </remarks>
        private static ImmutableArray<UnifiedSuggestedActionSet> PrioritizeFixGroups(
            ImmutableDictionary<CodeFixGroupKey, IList<UnifiedSuggestedAction>> map,
            ImmutableArray<CodeFixGroupKey> order,
            Workspace workspace)
        {
            using var _1 = ArrayBuilder<UnifiedSuggestedActionSet>.GetInstance(out var nonSuppressionSets);
            using var _2 = ArrayBuilder<UnifiedSuggestedActionSet>.GetInstance(out var suppressionSets);
            using var _3 = ArrayBuilder<UnifiedSuggestedAction>.GetInstance(out var bulkConfigurationActions);

            foreach (var groupKey in order)
            {
                var actions = map[groupKey];

                var nonSuppressionActions = actions.Where(a => !IsTopLevelSuppressionAction(a.OriginalCodeAction));
                AddUnifiedSuggestedActionsSet(nonSuppressionActions, groupKey, nonSuppressionSets);

                var suppressionActions = actions.Where(a => IsTopLevelSuppressionAction(a.OriginalCodeAction) &&
                    !IsBulkConfigurationAction(a.OriginalCodeAction));
                AddUnifiedSuggestedActionsSet(suppressionActions, groupKey, suppressionSets);

                bulkConfigurationActions.AddRange(actions.Where(a => IsBulkConfigurationAction(a.OriginalCodeAction)));
            }

            var sets = nonSuppressionSets.ToImmutable();

            // Append bulk configuration fixes at the end of suppression/configuration fixes.
            if (bulkConfigurationActions.Count > 0)
            {
                var bulkConfigurationSet = new UnifiedSuggestedActionSet(
                    UnifiedPredefinedSuggestedActionCategoryNames.CodeFix, bulkConfigurationActions.ToArray(),
                    title: null, priority: UnifiedSuggestedActionSetPriority.Lowest, applicableToSpan: null);
                suppressionSets.Add(bulkConfigurationSet);
            }

            if (suppressionSets.Count > 0)
            {
                // Wrap the suppression/configuration actions within another top level suggested action
                // to avoid clutter in the light bulb menu.
                var suppressOrConfigureCodeAction = new NoChangeAction(CodeFixesResources.Suppress_or_Configure_issues);
                var wrappingSuggestedAction = new UnifiedSuggestedActionWithNestedActions(
                    workspace, codeAction: suppressOrConfigureCodeAction,
                    codeActionPriority: suppressOrConfigureCodeAction.Priority, provider: null,
                    nestedActionSets: suppressionSets.ToImmutable());

                // Combine the spans and the category of each of the nested suggested actions
                // to get the span and category for the new top level suggested action.
                var (span, category) = CombineSpansAndCategory(suppressionSets);
                var wrappingSet = new UnifiedSuggestedActionSet(
                    category,
                    actions: SpecializedCollections.SingletonEnumerable(wrappingSuggestedAction),
                    title: CodeFixesResources.Suppress_or_Configure_issues,
                    priority: UnifiedSuggestedActionSetPriority.Lowest,
                    applicableToSpan: span);
                sets = sets.Add(wrappingSet);
            }

            return sets;

            // Local functions
            static (TextSpan? span, string category) CombineSpansAndCategory(IEnumerable<UnifiedSuggestedActionSet> sets)
            {
                // We are combining the spans and categories of the given set of suggested action sets
                // to generate a result span containing the spans of individual suggested action sets and
                // a result category which is the maximum severity category amongst the set
                var minStart = -1;
                var maxEnd = -1;
                var category = UnifiedPredefinedSuggestedActionCategoryNames.CodeFix;

                foreach (var set in sets)
                {
                    if (set.ApplicableToSpan.HasValue)
                    {
                        var currentStart = set.ApplicableToSpan.Value.Start;
                        var currentEnd = set.ApplicableToSpan.Value.End;

                        if (minStart == -1 || currentStart < minStart)
                        {
                            minStart = currentStart;
                        }

                        if (maxEnd == -1 || currentEnd > maxEnd)
                        {
                            maxEnd = currentEnd;
                        }
                    }

                    Debug.Assert(set.CategoryName is UnifiedPredefinedSuggestedActionCategoryNames.CodeFix or
                                 UnifiedPredefinedSuggestedActionCategoryNames.ErrorFix);

                    // If this set contains an error fix, then change the result category to ErrorFix
                    if (set.CategoryName == UnifiedPredefinedSuggestedActionCategoryNames.ErrorFix)
                    {
                        category = UnifiedPredefinedSuggestedActionCategoryNames.ErrorFix;
                    }
                }

                var combinedSpan = minStart >= 0 ? TextSpan.FromBounds(minStart, maxEnd) : (TextSpan?)null;
                return (combinedSpan, category);
            }
        }

        private static void AddUnifiedSuggestedActionsSet(
            IEnumerable<UnifiedSuggestedAction> actions,
            CodeFixGroupKey groupKey,
            ArrayBuilder<UnifiedSuggestedActionSet> sets)
        {
            foreach (var group in actions.GroupBy(a => a.CodeActionPriority))
            {
                var priority = GetUnifiedSuggestedActionSetPriority(group.Key);

                // diagnostic from things like build shouldn't reach here since we don't support LB for those diagnostics
                Debug.Assert(groupKey.Item1.HasTextSpan);
                var category = GetFixCategory(groupKey.Item1.Severity);
                sets.Add(new UnifiedSuggestedActionSet(
                    category, group, title: null, priority: priority, applicableToSpan: groupKey.Item1.GetTextSpan()));
            }
        }

        private static string GetFixCategory(DiagnosticSeverity severity)
        {
            switch (severity)
            {
                case DiagnosticSeverity.Hidden:
                case DiagnosticSeverity.Info:
                case DiagnosticSeverity.Warning:
                    return UnifiedPredefinedSuggestedActionCategoryNames.CodeFix;
                case DiagnosticSeverity.Error:
                    return UnifiedPredefinedSuggestedActionCategoryNames.ErrorFix;
                default:
                    throw ExceptionUtilities.Unreachable;
            }
        }

        private static bool IsTopLevelSuppressionAction(CodeAction action)
            => action is AbstractConfigurationActionWithNestedActions;

        private static bool IsBulkConfigurationAction(CodeAction action)
            => (action as AbstractConfigurationActionWithNestedActions)?.IsBulkConfigurationAction == true;

        /// <summary>
        /// Gets, filters, and orders code refactorings.
        /// </summary>
        public static async Task<ImmutableArray<UnifiedSuggestedActionSet>> GetFilterAndOrderCodeRefactoringsAsync(
            Workspace workspace,
            ICodeRefactoringService codeRefactoringService,
            Document document,
            TextSpan selection,
            bool isBlocking,
            Func<string, IDisposable?> addOperationScope,
            bool filterOutsideSelection,
            CancellationToken cancellationToken)
        {
            // It may seem strange that we kick off a task, but then immediately 'Wait' on
            // it. However, it's deliberate.  We want to make sure that the code runs on
            // the background so that no one takes an accidentally dependency on running on
            // the UI thread.
            var refactorings = await Task.Run(
                () => codeRefactoringService.GetRefactoringsAsync(
                    document, selection, isBlocking, addOperationScope,
                    cancellationToken), cancellationToken).ConfigureAwait(false);

            var filteredRefactorings = FilterOnAnyThread(refactorings, selection, filterOutsideSelection);

            return filteredRefactorings.SelectAsArray(
                r => OrganizeRefactorings(workspace, r));
        }

        private static ImmutableArray<CodeRefactoring> FilterOnAnyThread(
            ImmutableArray<CodeRefactoring> refactorings,
            TextSpan selection,
            bool filterOutsideSelection)
            => refactorings.Select(r => FilterOnAnyThread(r, selection, filterOutsideSelection)).WhereNotNull().ToImmutableArray();

        private static CodeRefactoring? FilterOnAnyThread(
            CodeRefactoring refactoring,
            TextSpan selection,
            bool filterOutsideSelection)
        {
            var actions = refactoring.CodeActions.WhereAsArray(IsActionAndSpanApplicable);
            return actions.Length == 0
                ? null
                : actions.Length == refactoring.CodeActions.Length
                    ? refactoring
                    : new CodeRefactoring(refactoring.Provider, actions);

            bool IsActionAndSpanApplicable((CodeAction action, TextSpan? applicableSpan) actionAndSpan)
            {
                if (filterOutsideSelection)
                {
                    // Filter out refactorings with applicable span outside the selection span.
                    if (!actionAndSpan.applicableSpan.HasValue ||
                        !selection.IntersectsWith(actionAndSpan.applicableSpan.Value))
                    {
                        return false;
                    }
                }

                return true;
            }
        }

        /// <summary>
        /// Arrange refactorings into groups.
        /// </summary>
        /// <remarks>
        /// Refactorings are returned in priority order determined based on <see cref="ExtensionOrderAttribute"/>.
        /// Priority for all <see cref="UnifiedSuggestedActionSet"/>s containing refactorings is set to
        /// <see cref="UnifiedSuggestedActionSetPriority.Low"/> and should show up after fixes but before
        /// suppression fixes in the light bulb menu.
        /// </remarks>
        private static UnifiedSuggestedActionSet OrganizeRefactorings(Workspace workspace, CodeRefactoring refactoring)
        {
            using var refactoringSuggestedActionsDisposer = ArrayBuilder<UnifiedSuggestedAction>.GetInstance(
                out var refactoringSuggestedActions);

            foreach (var codeAction in refactoring.CodeActions)
            {
                if (codeAction.action.NestedCodeActions.Length > 0)
                {
                    var nestedActions = codeAction.action.NestedCodeActions.SelectAsArray(
                        na => new UnifiedCodeRefactoringSuggestedAction(
                            workspace, na, na.Priority, refactoring.Provider));

                    var set = new UnifiedSuggestedActionSet(
                        categoryName: null,
                        actions: nestedActions,
                        title: null,
                        priority: GetUnifiedSuggestedActionSetPriority(codeAction.action.Priority),
                        applicableToSpan: codeAction.applicableToSpan);

                    refactoringSuggestedActions.Add(
                        new UnifiedSuggestedActionWithNestedActions(
                            workspace, codeAction.action, codeAction.action.Priority, refactoring.Provider, ImmutableArray.Create(set)));
                }
                else
                {
                    refactoringSuggestedActions.Add(
                        new UnifiedCodeRefactoringSuggestedAction(
                            workspace, codeAction.action, codeAction.action.Priority, refactoring.Provider));
                }
            }

            var actions = refactoringSuggestedActions.ToImmutable();

            // An action set:
            // - gets the the same priority as the highest priority action within in.
            // - gets `applicableToSpan` of the first action:
            //   - E.g. the `applicableToSpan` closest to current selection might be a more correct
            //     choice. All actions created by one Refactoring have usually the same `applicableSpan`
            //     and therefore the complexity of determining the closest one isn't worth the benefit
            //     of slightly more correct orderings in certain edge cases.
            return new UnifiedSuggestedActionSet(
                UnifiedPredefinedSuggestedActionCategoryNames.Refactoring,
                actions: actions,
                title: null,
                priority: GetUnifiedSuggestedActionSetPriority(actions.Max(a => a.CodeActionPriority)),
                applicableToSpan: refactoring.CodeActions.FirstOrDefault().applicableToSpan);
        }

        private static UnifiedSuggestedActionSetPriority GetUnifiedSuggestedActionSetPriority(CodeActionPriority key)
            => key switch
            {
                CodeActionPriority.Lowest => UnifiedSuggestedActionSetPriority.Lowest,
                CodeActionPriority.Low => UnifiedSuggestedActionSetPriority.Low,
                CodeActionPriority.Medium => UnifiedSuggestedActionSetPriority.Medium,
                CodeActionPriority.High => UnifiedSuggestedActionSetPriority.High,
                _ => throw new InvalidOperationException(),
            };

        /// <summary>
        /// Filters and orders the code fix sets and code refactoring sets amongst each other.
        /// Should be called with the results from <see cref="GetFilterAndOrderCodeFixesAsync"/>
        /// and <see cref="GetFilterAndOrderCodeRefactoringsAsync"/>.
        /// </summary>
        public static ImmutableArray<UnifiedSuggestedActionSet> FilterAndOrderActionSets(
            ImmutableArray<UnifiedSuggestedActionSet> fixes,
            ImmutableArray<UnifiedSuggestedActionSet> refactorings,
            TextSpan? selectionOpt)
        {
            // Get the initial set of action sets, with refactorings and fixes appropriately
            // ordered against each other.
            var result = GetInitiallyOrderedActionSets(selectionOpt, fixes, refactorings);
            if (result.IsEmpty)
                return ImmutableArray<UnifiedSuggestedActionSet>.Empty;

            // Now that we have the entire set of action sets, inline, sort and filter
            // them appropriately against each other.
            var allActionSets = InlineActionSetsIfDesirable(result);
            var orderedActionSets = OrderActionSets(allActionSets, selectionOpt);
            var filteredSets = FilterActionSetsByTitle(orderedActionSets);

            return filteredSets;
        }

        private static ImmutableArray<UnifiedSuggestedActionSet> GetInitiallyOrderedActionSets(
            TextSpan? selectionOpt,
            ImmutableArray<UnifiedSuggestedActionSet> fixes,
            ImmutableArray<UnifiedSuggestedActionSet> refactorings)
        {
            // First, order refactorings based on the order the providers actually gave for
            // their actions. This way, a low pri refactoring always shows after a medium pri
            // refactoring, no matter what we do below.
            refactorings = OrderActionSets(refactorings, selectionOpt);

            // If there's a selection, it's likely the user is trying to perform some operation
            // directly on that operation (like 'extract method').  Prioritize refactorings over
            // fixes in that case.  Otherwise, it's likely that the user is just on some error
            // and wants to fix it (in which case, prioritize fixes).

            if (selectionOpt?.Length > 0)
            {
                // There was a selection.  Treat refactorings as more important than fixes.
                // Note: we still will sort after this.  So any high pri fixes will come to the
                // front.  Any low-pri refactorings will go to the end.
                return refactorings.Concat(fixes);
            }
            else
            {
                // No selection.  Treat all medium and low pri refactorings as low priority, and
                // place after fixes.  Even a low pri fixes will be above what was *originally*
                // a medium pri refactoring.
                //
                // Note: we do not do this for *high* pri refactorings (like 'rename').  These
                // are still very important and need to stay at the top (though still after high
                // pri fixes).
                var highPriRefactorings = refactorings.WhereAsArray(
                    s => s.Priority == UnifiedSuggestedActionSetPriority.High);
                var nonHighPriRefactorings = refactorings.WhereAsArray(
                    s => s.Priority != UnifiedSuggestedActionSetPriority.High)
                        .SelectAsArray(s => WithPriority(s, UnifiedSuggestedActionSetPriority.Low));

                var highPriFixes = fixes.WhereAsArray(s => s.Priority == UnifiedSuggestedActionSetPriority.High);
                var nonHighPriFixes = fixes.WhereAsArray(s => s.Priority != UnifiedSuggestedActionSetPriority.High);

                return highPriFixes.Concat(highPriRefactorings).Concat(nonHighPriFixes).Concat(nonHighPriRefactorings);
            }
        }

        private static ImmutableArray<UnifiedSuggestedActionSet> OrderActionSets(
            ImmutableArray<UnifiedSuggestedActionSet> actionSets, TextSpan? selectionOpt)
        {
            return actionSets.OrderByDescending(s => s.Priority)
                             .ThenBy(s => s, new UnifiedSuggestedActionSetComparer(selectionOpt))
                             .ToImmutableArray();
        }

        private static UnifiedSuggestedActionSet WithPriority(
            UnifiedSuggestedActionSet set, UnifiedSuggestedActionSetPriority priority)
            => new(set.CategoryName, set.Actions, set.Title, priority, set.ApplicableToSpan);

        private static ImmutableArray<UnifiedSuggestedActionSet> InlineActionSetsIfDesirable(
            ImmutableArray<UnifiedSuggestedActionSet> allActionSets)
        {
            // If we only have a single set of items, and that set only has three max suggestion
            // offered. Then we can consider inlining any nested actions into the top level list.
            // (but we only do this if the parent of the nested actions isn't invokable itself).
            if (allActionSets.Sum(a => a.Actions.Count()) > 3)
            {
                return allActionSets;
            }

            return allActionSets.SelectAsArray(InlineActions);
        }

        private static UnifiedSuggestedActionSet InlineActions(UnifiedSuggestedActionSet actionSet)
        {
            using var newActionsDisposer = ArrayBuilder<IUnifiedSuggestedAction>.GetInstance(out var newActions);
            foreach (var action in actionSet.Actions)
            {
                var actionWithNestedActions = action as UnifiedSuggestedActionWithNestedActions;

                // Only inline if the underlying code action allows it.
                if (actionWithNestedActions?.OriginalCodeAction.IsInlinable == true)
                {
                    newActions.AddRange(actionWithNestedActions.NestedActionSets.SelectMany(set => set.Actions));
                }
                else
                {
                    newActions.Add(action);
                }
            }

            return new UnifiedSuggestedActionSet(
                actionSet.CategoryName,
                newActions.ToImmutable(),
                actionSet.Title,
                actionSet.Priority,
                actionSet.ApplicableToSpan);
        }

        private static ImmutableArray<UnifiedSuggestedActionSet> FilterActionSetsByTitle(
            ImmutableArray<UnifiedSuggestedActionSet> allActionSets)
        {
            using var resultDisposer = ArrayBuilder<UnifiedSuggestedActionSet>.GetInstance(out var result);
            var seenTitles = new HashSet<string>();

            foreach (var set in allActionSets)
            {
                var filteredSet = FilterActionSetByTitle(set, seenTitles);
                if (filteredSet != null)
                {
                    result.Add(filteredSet);
                }
            }

            return result.ToImmutable();
        }

        private static UnifiedSuggestedActionSet? FilterActionSetByTitle(UnifiedSuggestedActionSet set, HashSet<string> seenTitles)
        {
            using var actionsDisposer = ArrayBuilder<IUnifiedSuggestedAction>.GetInstance(out var actions);

            foreach (var action in set.Actions)
            {
                if (seenTitles.Add(action.OriginalCodeAction.Title))
                {
                    actions.Add(action);
                }
            }

            return actions.Count == 0
                ? null
                : new UnifiedSuggestedActionSet(set.CategoryName, actions.ToImmutable(), set.Title, set.Priority, set.ApplicableToSpan);
        }
    }
}


text:
Main Features
==============

An important aspect of *Graphs.jl* is the generic abstraction of graph concepts expressed via standardized interfaces, which allows access to a graph's structure while hiding the implementation details. This encourages reuse of data structures and algorithms. In particular, one can write generic graph algorithms that can be applied to different graph types as long as they implement the required interface.

In addition to the generic abstraction, there are other important features:

* A variety of graph types tailored to different purposes
    - generic adjacency list
    - generic incidence list
    - a simple graph type with compact and efficient representation
    - an extended graph type that supports labels and attributes

* A collection of graph algorithms:
    - graph traversal with visitor support: BFS, DFS
    - cycle detection
    - connected components
    - topological sorting
    - shortest paths: Dijkstra, Floyd-Warshall
    - minimum spanning trees: Prim, Kruskal
    - more algorithms are being implemented

* Matrix-based characterization: adjacency matrix, weight matrix, Laplacian matrix

* All data structures and algorithms are implemented in *pure Julia*, and thus they are portable.

* We paid special attention to the runtime performance. Many of the algorithms are very efficient. For example, a benchmark shows that it takes about *15 milliseconds* to run the Dijkstra's algorithm over a graph with *10 thousand* vertices and *1 million*  edges on a macbook pro.