public static void show() {
    if (shownInSession) {
      return;
    }
    shownInSession = true;
    if (SharedCorePlugin.inTestMode()) {
      return;
    }
    String hide = System.getProperty("pydev.funding.hide");
    if (hide != null && (hide.equals("1") || hide.equals("true"))) {
      return;
    }
    IPreferenceStore preferenceStore = PydevPrefs.getPreferenceStore();
    boolean shownOnce = preferenceStore.getBoolean(PYDEV_FUNDING_SHOWN);
    if (!shownOnce) {
      boolean runNowIfInUiThread = false;
      RunInUiThread.async(
          new Runnable() {

            @Override
            public void run() {
              Display disp = Display.getCurrent();
              Shell shell = new Shell(disp);
              DialogNotifier notifier = new DialogNotifier(shell);
              notifier.open();
            }
          },
          runNowIfInUiThread);
    }
  }
  @Override
  public void paintControl(PaintEvent e) {

    if (inDraw || styledText == null || styledText.isDisposed()) {
      return;
    }
    try {
      inDraw = true;
      boolean showIndentGuide = this.indentGuide.getShowIndentGuide();
      if (!showIndentGuide) {
        return;
      }

      int xOffset = styledText.getHorizontalPixel();
      int yOffset = styledText.getTopPixel();

      // Important: call all to cache the new values (instead of doing all inside the or below).
      boolean styledTextContentChanged = getStyledTextContentChangedAndStoreNew();
      boolean clientAreaChanged = getClientAreaChangedAndStoreNew();
      boolean charCountChanged = getCharCountChangedAndStoreNew();
      boolean tabWidthChanged = getTabWidthChangedAndStoreNew();

      boolean redrawAll =
          styledTextContentChanged
              || clientAreaChanged
              || charCountChanged
              || tabWidthChanged
              || xOffset != lastXOffset
              || yOffset != lastYOffset;

      StyledTextContent currentContent = this.content;
      if (currClientArea == null
          || currClientArea.width < 5
          || currClientArea.height < 5
          || currCharCount < 1
          || currentContent == null
          || currTabWidth <= 0) {
        return;
      }
      lastXOffset = xOffset;
      lastYOffset = yOffset;

      int topIndex;
      try {
        topIndex = JFaceTextUtil.getPartialTopIndex(styledText);
      } catch (IllegalArgumentException e1) {
        // Just silence it...
        // java.lang.IllegalArgumentException: Index out of bounds
        // at org.eclipse.swt.SWT.error(SWT.java:4458)
        // at org.eclipse.swt.SWT.error(SWT.java:4392)
        // at org.eclipse.swt.SWT.error(SWT.java:4363)
        // at org.eclipse.swt.custom.StyledText.getOffsetAtLine(StyledText.java:4405)
        // at org.eclipse.jface.text.JFaceTextUtil.getPartialTopIndex(JFaceTextUtil.java:103)
        // at
        // org.python.pydev.shared_ui.editor.VerticalIndentGuidesPainter.paintControl(VerticalIndentGuidesPainter.java:93)
        return;
      }
      int bottomIndex = JFaceTextUtil.getPartialBottomIndex(styledText);
      if (redrawAll) {
        this.lineToVerticalLinesToDraw =
            this.indentGuide.computeVerticalLinesToDrawInRegion(styledText, topIndex, bottomIndex);
        // This is a bit unfortunate: when something changes, we may have to repaint out of the
        // clipping
        // region, but even setting the clipping region (e.gc.setClipping), the clipping region may
        // still
        // be unchanged (because the system said that it only wants to repaint some specific area
        // already
        // and we can't make it bigger -- so, what's left for us is asking for a repaint of the full
        // area
        // in this case).
        if (askFullRedraw) {
          askFullRedraw = false;
          if (Math.abs(currClientArea.height - e.gc.getClipping().height) > 40) {
            // Only do it if the difference is really high (some decorations make it usually a bit
            // lower than
            // the actual client area -- usually around 14 in my tests, but make it a bit higher as
            // the usual
            // difference when a redraw is needed is pretty high).
            RunInUiThread.async(
                new Runnable() {

                  @Override
                  public void run() {
                    StyledText s = styledText;
                    if (s != null && !s.isDisposed()) {
                      s.redraw();
                    }
                  }
                });
          } else {
          }
        }
      }

      if (this.lineToVerticalLinesToDraw != null) {
        try (AutoCloseable temp = configGC(e.gc)) {
          Collection<List<VerticalLinesToDraw>> values = lineToVerticalLinesToDraw.values();
          for (List<VerticalLinesToDraw> list : values) {
            for (VerticalLinesToDraw verticalLinesToDraw : list) {
              verticalLinesToDraw.drawLine(e.gc);
            }
          }
        }
      }
    } catch (Exception e1) {
      Log.log(e1);
    } finally {
      inDraw = false;
    }
  }
  /**
   * Adds a set of arguments used to wrap executed file with unittest runner.
   *
   * @param actualRun in an actual run we'll start the xml-rpc server.
   * @param coverageRun whether we should add the flags to do a coverage run.
   */
  private void addUnittestArgs(List<String> cmdArgs, boolean actualRun, boolean coverageRun)
      throws CoreException {
    if (isUnittest()) {

      // The tests are either written to a configuration file or passed as a parameter.
      String configurationFile =
          this.configuration.getAttribute(Constants.ATTR_UNITTEST_CONFIGURATION_FILE, "");
      if (configurationFile.length() > 0) {
        cmdArgs.add("--config_file");
        if (actualRun) {
          // We should write the contents to a temporary file (because it may be too long, so,
          // always write
          // to a file and read from it later on).
          File tempFile = PydevPlugin.getDefault().getTempFile("custom_pydev_unittest_launch_");
          try {
            OutputStream fileOutputStream = new FileOutputStream(tempFile);
            try {
              try {
                fileOutputStream.write(configurationFile.getBytes());
              } catch (IOException e) {
                throw new CoreException(
                    PydevPlugin.makeStatus(IStatus.ERROR, "Error writing to: " + tempFile, e));
              }
            } finally {
              fileOutputStream.close();
            }
          } catch (Exception e) {
            if (e instanceof CoreException) {
              throw (CoreException) e;
            }
            throw new CoreException(
                PydevPlugin.makeStatus(IStatus.ERROR, "Error writing to: " + tempFile, e));
          }
          cmdArgs.add(tempFile.toString());
        } else {
          cmdArgs.add(configurationFile);
        }
      } else {
        String tests = this.configuration.getAttribute(Constants.ATTR_UNITTEST_TESTS, "");
        if (tests.length() > 0) {
          cmdArgs.add("--tests");
          cmdArgs.add(tests);
        }
      }

      if (PyUnitPrefsPage2.getUsePyUnitView()) {
        // If we want to use the PyUnitView, we need to get the port used so that the python side
        // can connect.
        cmdArgs.add("--port");
        if (actualRun) {
          cmdArgs.add(String.valueOf(getPyUnitServer().getPort()));
        } else {
          cmdArgs.add("0");
        }
      }

      if (coverageRun) {
        cmdArgs.add("--coverage_output_dir");
        cmdArgs.add(PyCoverage.getCoverageDirLocation().getAbsolutePath());

        cmdArgs.add("--coverage_include");
        cmdArgs.add(PyCodeCoverageView.getChosenDir().getLocation().toOSString());

        if (actualRun) {
          IPreferenceStore prefs = PydevPrefs.getPreferenceStore();
          int testRunner = prefs.getInt(PyUnitPrefsPage2.TEST_RUNNER);

          switch (testRunner) {
            case PyUnitPrefsPage2.TEST_RUNNER_NOSE:
              RunInUiThread.async(
                  new Runnable() {

                    public void run() {
                      PyDialogHelpers.openWarningWithIgnoreToggle(
                          "Notes for coverage with the nose test runner.",
                          "Note1: When using the coverage with the nose test runner, "
                              + "please don't pass any specific parameter related to "
                              + "the run in the arguments, as that's already handled by PyDev "
                              + "(i.e.: don't use the builtin cover plugin from nose).\n"
                              + "\n"
                              + "Note2: It's currently not possible to use coverage with the multi-process "
                              + "plugin in nose.",
                          "KEY_COVERAGE_WITH_NOSE_TEST_RUNNER");
                    }
                  });

              break;
            case PyUnitPrefsPage2.TEST_RUNNER_PY_TEST:
              RunInUiThread.async(
                  new Runnable() {

                    public void run() {
                      PyDialogHelpers.openCritical(
                          "PyUnit coverage not compatible with the Py.test test runner.",
                          "Currently the PyDev PyUnit integration is not able to provide coverage "
                              + "info using the py.test test runner (please enter a "
                              + "feature request if you'd like that added)\n"
                              + "\n"
                              + "Note: the run will be continued anyways (without gathering coverage info).");
                    }
                  });
              break;
          }
        }
      }

      // Last thing: nose parameters or parameters the user configured.
      for (String s :
          parseStringIntoList(
              PyUnitPrefsPage2.getTestRunnerParameters(this.configuration, this.project))) {
        cmdArgs.add(s);
      }
    }
  }
  /**
   * Create a command line for launching.
   *
   * @param actualRun if true it'll make the variable substitution and start the listen connector in
   *     the case of a debug session.
   * @return command line ready to be exec'd
   * @throws CoreException
   * @throws JDTNotAvailableException
   */
  public String[] getCommandLine(boolean actualRun) throws CoreException, JDTNotAvailableException {
    List<String> cmdArgs = new ArrayList<String>();

    if (isJython()) {
      // "java.exe" -classpath "C:\bin\jython21\jython.jar" org.python.util.jython script %ARGS%
      String javaLoc = JavaVmLocationFinder.findDefaultJavaExecutable().getAbsolutePath();
      if (!InterpreterInfo.isJythonExecutable(interpreter.toOSString())) {
        throw new RuntimeException(
            "The jython jar must be specified as the interpreter to run. Found: " + interpreter);
      }
      cmdArgs.add(javaLoc);

      // some nice things on the classpath config: http://mindprod.com/jgloss/classpath.html
      cmdArgs.add("-classpath");
      String cpath;

      // TODO: add some option in the project so that the user can choose to use the
      // classpath specified in the java project instead of the pythonpath itself

      //            if (project.getNature(Constants.JAVA_NATURE) != null){
      //                cpath  = getClasspath(JavaCore.create(project));
      //            } else {
      cpath = interpreter + SimpleRunner.getPythonPathSeparator() + pythonpathUsed;
      //            }
      cmdArgs.add(cpath);
      cmdArgs.add(
          "-Dpython.path="
              + pythonpathUsed); // will be added to the env variables in the run (check if this
      // works on all platforms...)

      addVmArgs(cmdArgs);

      if (isDebug) {
        // This was removed because it cannot be used. See:
        // http://bugs.jython.org/issue1438
        // cmdArgs.add("-Dpython.security.respectJavaAccessibility=false");

        cmdArgs.add("org.python.util.jython");
        addDebugArgs(cmdArgs, "jython", actualRun);
      } else {
        cmdArgs.add("org.python.util.jython");
      }

    } else {
      // python or iron python

      cmdArgs.add(interpreter.toOSString());
      // Next option is for unbuffered stdout, otherwise Eclipse will not see any output until done
      cmdArgs.add("-u");

      addVmArgs(cmdArgs);
      if (isDebug && isIronpython()) {
        addIronPythonDebugVmArgs(cmdArgs);
      }

      addDebugArgs(cmdArgs, "python", actualRun);
    }

    // Check if we should do code-coverage...
    boolean coverageRun = PyCoveragePreferences.getAllRunsDoCoverage();
    if (coverageRun && isDebug) {
      if (actualRun) {
        RunInUiThread.async(
            new Runnable() {

              public void run() {
                PyDialogHelpers.openWarning(
                    "Conflicting options: coverage with debug.",
                    "Making a debug run with coverage enabled will not yield the expected results.\n\n"
                        + "They'll conflict because both use the python tracing facility (i.e.: sys.settrace()).\n"
                        + "\n"
                        + "To debug a coverage run, do a regular run and use the remote debugger "
                        + "(but note that the coverage will stop when it's enabled).\n"
                        + "\n"
                        + "Note: the run will be continued anyways.");
              }
            });
      }
    }

    if (isUnittest()) {
      cmdArgs.add(getRunFilesScript());
    } else {
      if (coverageRun) {
        // Separate support (unittest has the coverage support builtin).
        cmdArgs.add(getCoverageScript());
        cmdArgs.add(PyCoverage.getCoverageFileLocation().getAbsolutePath());
        cmdArgs.add("run");
        cmdArgs.add("--source");
        cmdArgs.add(PyCodeCoverageView.getChosenDir().getLocation().toOSString());
      }
    }

    for (IPath p : resource) {
      cmdArgs.add(p.toOSString());
    }

    if (!isUnittest()) {
      // The program arguments are not used when running a unittest (excluded from the tab group in
      // favor
      // of a way to overriding the default unittest arguments).
      String runArguments[] = null;
      if (actualRun && arguments != null) {
        String expanded =
            getStringSubstitution(PythonNature.getPythonNature(project))
                .performStringSubstitution(arguments);
        runArguments = parseStringIntoList(expanded);
      }

      for (int i = 0; runArguments != null && i < runArguments.length; i++) {
        cmdArgs.add(runArguments[i]);
      }

    } else {
      // Last thing (first the files and last the special parameters the user passed -- i.e.: nose
      // parameters)
      addUnittestArgs(cmdArgs, actualRun, coverageRun);
    }

    String[] retVal = new String[cmdArgs.size()];
    cmdArgs.toArray(retVal);

    if (actualRun) {
      CreatedCommandLineParams createdCommandLineParams =
          new CreatedCommandLineParams(retVal, coverageRun);
      // Provide a way for clients to alter the command line.
      List<Object> participants =
          ExtensionHelper.getParticipants(ExtensionHelper.PYDEV_COMMAND_LINE_PARTICIPANT);
      for (Object object : participants) {
        try {
          IPyCommandLineParticipant c = (IPyCommandLineParticipant) object;
          createdCommandLineParams = c.updateCommandLine(createdCommandLineParams);
        } catch (Exception e) {
          Log.log(e);
        }
      }

      retVal = createdCommandLineParams.cmdLine;
      PythonRunnerCallbacks.onCreatedCommandLine.call(createdCommandLineParams);
    }

    return retVal;
  }