about summary refs log tree commit diff
path: root/pkgs/applications
diff options
context:
space:
mode:
authorCOLAMAroro <github@rondier.io>2023-03-18 16:34:10 +0100
committerCOLAMAroro <github@rondier.io>2023-04-06 15:02:29 +0200
commitaa4cf231c4d1d062dd5e91d5d7807da4442c4f5f (patch)
tree998b942b08cc013a538eb93c7677ed7d4ccccb38 /pkgs/applications
parentbcd59cec7b03786c0173f3b41d3623d6186cabfa (diff)
pulsar: init at 1.103.0
Community maintained fork of the sunset Atom editor.
https://github.com/pulsar-edit/pulsar
Diffstat (limited to 'pkgs/applications')
-rw-r--r--pkgs/applications/editors/pulsar/001-patch-wrapper.patch27
-rw-r--r--pkgs/applications/editors/pulsar/default.nix163
-rw-r--r--pkgs/applications/editors/pulsar/pulsar.nemo_action9
-rwxr-xr-xpkgs/applications/editors/pulsar/update.mjs89
4 files changed, 288 insertions, 0 deletions
diff --git a/pkgs/applications/editors/pulsar/001-patch-wrapper.patch b/pkgs/applications/editors/pulsar/001-patch-wrapper.patch
new file mode 100644
index 0000000000000..252dc5328ef29
--- /dev/null
+++ b/pkgs/applications/editors/pulsar/001-patch-wrapper.patch
@@ -0,0 +1,27 @@
+--- a/resources/pulsar.sh	2023-03-16 04:11:14.000000000 +0100
++++ b/resources/pulsar.sh	2023-03-24 14:37:13.468813964 +0100
+@@ -123,22 +123,9 @@
+ elif [ $OS == 'Linux' ]; then
+   SCRIPT=$(readlink -f "$0")
+ 
+-  PULSAR_PATH="/opt/Pulsar/pulsar"
++  # PULSAR_PATH is set-up via `wrapProgram` in the postFixup phase
+
+-  #Will allow user to get context menu on cinnamon desktop enviroment
+-  #Add a check to make sure that DESKTOP_SESSION is set before attempting to grep it
+-  #expr substr is expecting 3 arguments string, index, length
+-  #If grep doesnt find anything is provides an empty string which causes the expr: syntax error: missing argument after '8' error - see pulsar-edit/pulsar#174
+-  #Im also not quite sure why they used grep instead of simply [ "${DESKTOP_SESSION}" == "cinnamon" ]
+-  if [ -n "${DESKTOP_SESSION}" ] && [ "$(expr substr $(printenv | grep 'DESKTOP_SESSION=') 17 8)" == "cinnamon" ]; then
+-    #This local path is almost assuredly wrong as it shouldnt exist in a standard install
+-    ACTION_PATH="resources/linux/desktopenviroment/cinnamon/pulsar.nemo_action"
+-
+-    #Validate the file exists before attempting to copy it
+-    if [ -f "${ACTION_PATH}" ]; then
+-        cp "${$ACTION_PATH}" "/usr/share/nemo/actions/pulsar.nemo_action"
+-    fi
+-  fi
++  # We remove the nemo integration. It is handled by the postFixup phase
+ 
+   #Set tmpdir only if tmpdir is unset
+   : ${TMPDIR:=/tmp}
diff --git a/pkgs/applications/editors/pulsar/default.nix b/pkgs/applications/editors/pulsar/default.nix
new file mode 100644
index 0000000000000..545cd95f6f551
--- /dev/null
+++ b/pkgs/applications/editors/pulsar/default.nix
@@ -0,0 +1,163 @@
+{ lib
+, stdenv
+, git
+, runtimeShell
+, fetchurl
+, wrapGAppsHook
+, glib
+, gtk3
+, atomEnv
+, xorg
+, libxkbcommon
+, hunspell
+, hunspellDicts
+, useHunspell ? true
+, languages ? [ "en_US" ]
+, withNemoAction ? true
+, makeDesktopItem
+, copyDesktopItems
+, makeWrapper
+}:
+
+let
+  pname = "Pulsar";
+  version = "1.103.0";
+
+  sourcesPath = {
+    x86_64-linux.tarname = "Linux.${pname}-${version}.tar.gz";
+    x86_64-linux.hash = "sha256-C9La+rMpxyFthNPwPBZfV1goP/F1TiNYYYwmPCSkKdw=";
+    aarch64-linux.tarname = "ARM.Linux.${pname}-${version}-arm64.tar.gz";
+    aarch64-linux.hash = "sha256-uVGxDLqFgm5USZT6i7pLYJZq8jFxZviVXXYTL3RVhpw=";
+  }.${stdenv.hostPlatform.system} or (throw "Unsupported system: ${stdenv.hostPlatform.system}");
+
+  additionalLibs = lib.makeLibraryPath [
+    xorg.libxshmfence
+    libxkbcommon
+    xorg.libxkbfile
+  ];
+  newLibpath = "${atomEnv.libPath}:${additionalLibs}";
+
+  # Hunspell
+  hunspellDirs = builtins.map (lang: "${hunspellDicts.${lang}}/share/hunspell") languages;
+  hunspellTargetDirs = "$out/opt/Pulsar/resources/app.asar.unpacked/node_modules/spellchecker/vendor/hunspell_dictionaries";
+  hunspellCopyCommands = lib.concatMapStringsSep "\n" (lang: "cp -r ${lang}/* ${hunspellTargetDirs};") hunspellDirs;
+in
+stdenv.mkDerivation rec {
+  inherit pname version;
+
+  src = with sourcesPath; fetchurl {
+    url = "https://github.com/pulsar-edit/pulsar/releases/download/v${version}/${tarname}";
+    inherit hash;
+  };
+
+  patches = [
+    ./001-patch-wrapper.patch
+  ];
+
+  nativeBuildInputs = [
+    wrapGAppsHook
+    copyDesktopItems
+  ];
+
+  buildInputs = [
+    gtk3
+    xorg.libxkbfile
+  ];
+
+  dontBuild = true;
+  dontConfigure = true;
+
+  installPhase = ''
+    runHook preInstall
+
+    mkdir -p $out/opt/Pulsar
+    mv * $out/opt/Pulsar
+
+    runHook postInstall
+  '';
+
+  preFixup = ''
+    gappsWrapperArgs+=(
+      # needed for gio executable to be able to delete files
+      --prefix "PATH" : "${lib.makeBinPath [ glib ]}"
+    )
+  '' + lib.optionalString useHunspell ''
+    # On all platforms, we must inject our dictionnaries
+    ${hunspellCopyCommands}
+  '';
+
+  postFixup = ''
+    opt=$out/opt/Pulsar
+    # Patch the prebuilt binaries
+    patchelf --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" \
+      --set-rpath "${newLibpath}:$opt" \
+      --add-needed libffmpeg.so \
+      --add-needed libxshmfence.so.1 \
+      --add-needed libxkbcommon.so.0 \
+      --add-needed libxkbfile.so.1 \
+      --add-needed libsecret-1.so.0 \
+      $opt/pulsar
+    patchelf --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" \
+      --set-rpath "${newLibpath}" \
+      $opt/resources/app/ppm/bin/node
+    patchelf --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" \
+      $opt/resources/app.asar.unpacked/node_modules/symbols-view/vendor/ctags-linux
+
+  '' + lib.optionalString (stdenv.hostPlatform.system == "x86_64-linux") ''
+    # Replace the bundled git with the one from nixpkgs
+    dugite=$opt/resources/app.asar.unpacked/node_modules/dugite
+    rm -f $dugite/git/bin/git
+    ln -s ${git}/bin/git $dugite/git/bin/git
+    rm -f $dugite/git/libexec/git-core/git
+    ln -s ${git}/bin/git $dugite/git/libexec/git-core/git
+  '' + ''
+    # Patch the bundled node executables
+    find $opt -name "*.node" -exec patchelf --set-rpath "${newLibpath}:$opt" {} \;
+    # Also patch the node executable for apm
+    patchelf --set-rpath "${newLibpath}:$opt" $opt/resources/app/ppm/bin/node
+
+    # We have patched the original wrapper, but now it needs the "PULSAR_PATH" env var
+    mkdir -p $out/bin
+    wrapProgram $opt/resources/pulsar.sh \
+      --prefix "PULSAR_PATH" : "$opt/pulsar"
+    ln -s $opt/resources/pulsar.sh $out/bin/pulsar
+    ln -s $opt/resources/app/ppm/bin/apm $out/bin/ppm
+
+    # Copy the icons
+    mkdir -p $out/share/icons/hicolor/scalable/apps $out/share/icons/hicolor/1024x1024/apps
+    cp $opt/resources/pulsar.svg $out/share/icons/hicolor/scalable/apps/pulsar.svg
+    cp $opt/resources/pulsar.png $out/share/icons/hicolor/1024x1024/apps/pulsar.png
+  '' + lib.optionalString withNemoAction ''
+    # Copy the nemo action file
+    mkdir -p $out/share/nemo/actions
+    cp ${./pulsar.nemo_action} $out/share/nemo/actions/pulsar.nemo_action
+  '';
+
+  desktopItems = [
+    (makeDesktopItem {
+      name = "Pulsar";
+      desktopName = "Pulsar";
+      exec = "pulsar";
+      icon = "pulsar";
+      comment = "A Community-led Hyper-Hackable Text Editor";
+      genericName = "Text Editor";
+      categories = [ "Development" "TextEditor" "Utility" ];
+      mimeTypes = [ "text/plain" ];
+    })
+  ];
+
+  passthru.updateScript = ./update.mjs;
+
+  meta = with lib; {
+    description = "A Community-led Hyper-Hackable Text Editor";
+    longDescription = ''
+      A Community-led Hyper-Hackable Text Editor, Forked from Atom, built on Electron.
+      Designed to be deeply customizable, but still approachable using the default configuration.
+    '';
+    homepage = "https://github.com/pulsar-edit/pulsar";
+    sourceProvenance = with sourceTypes; [ binaryNativeCode ];
+    license = licenses.mit;
+    platforms = platforms.linux;
+    maintainers = with maintainers; [ colamaroro ];
+  };
+}
diff --git a/pkgs/applications/editors/pulsar/pulsar.nemo_action b/pkgs/applications/editors/pulsar/pulsar.nemo_action
new file mode 100644
index 0000000000000..a74d7324ecce3
--- /dev/null
+++ b/pkgs/applications/editors/pulsar/pulsar.nemo_action
@@ -0,0 +1,9 @@
+[Nemo Action]
+Active=true
+Name=Open in Pulsar
+Comment=Open in Pulsar
+#%U is the current selected file, this will also work on current directory
+Exec=pulsar -n %U
+Icon-Name=pulsar
+Selection=any
+Extensions=any
diff --git a/pkgs/applications/editors/pulsar/update.mjs b/pkgs/applications/editors/pulsar/update.mjs
new file mode 100755
index 0000000000000..ecddbbbb9b8af
--- /dev/null
+++ b/pkgs/applications/editors/pulsar/update.mjs
@@ -0,0 +1,89 @@
+#!/usr/bin/env nix-shell
+/*
+#!nix-shell -i node -p nodejs-18_x
+*/
+
+import { promises as fs } from 'node:fs';
+import { promisify } from 'node:util';
+import { exec as _exec } from 'node:child_process';
+const exec = promisify(_exec);
+
+const constants = {
+    githubUrl: "https://api.github.com/repos/pulsar-edit/pulsar/releases",
+    sha256FileURL: (newVersion) => `https://github.com/pulsar-edit/pulsar/releases/download/v${newVersion}/SHA256SUMS.txt`,
+    x86_64FileName: (newVersion) => `Linux.pulsar-${newVersion}.tar.gz`,
+    aarch64FileName: (newVersion) => `ARM.Linux.pulsar-${newVersion}-arm64.tar.gz`,
+};
+
+async function getLatestVersion() {
+    const requestResult = await fetch(constants.githubUrl);
+    if (!requestResult.ok) {
+        console.error("Failed to fetch releases");
+        console.error(requestResult);
+        process.exit(1);
+    };
+    let jsonResult = await requestResult.json();
+
+    jsonResult = jsonResult.filter((release) => !release.prerelease && !release.draft);
+    if (jsonResult.length == 0) {
+        console.error("No releases found");
+        process.exit(1);
+    }
+
+    return jsonResult[0].tag_name.replace(/^v/, '');
+}
+
+async function getSha256Sum(hashFileContent, targetFile) {
+    // The upstream file has a fomat like this:
+    // 0000000000000000000000000000000000000000000000000000000000000000 targetFile
+
+    let sha256 = hashFileContent.
+        split('\n').
+        filter((line) => line.endsWith(targetFile))[0].
+        split(' ')[0];
+
+    return "sha256-" + Buffer.from(sha256, 'hex').toString('base64');
+}
+
+async function getSha256Sums(newVersion) {
+    // Upstream provides a file with the hashes of the files, but it's not in the SRI format, and it refers to the compressed tarball
+    // So let's just use nix-prefetch-url to get the hashes of the decompressed tarball, and `nix hash to-sri` to convert them to SRI format
+    const hashFileUrl = constants.sha256FileURL(newVersion);
+    const hashFileContent = await fetch(hashFileUrl).then((response) => response.text());
+
+    let x86_64;
+    let aarch64;
+    console.log("Getting new hashes");
+    let promises = [
+        getSha256Sum(hashFileContent, constants.x86_64FileName(newVersion)).then((hash) => { x86_64 = hash; }),
+        getSha256Sum(hashFileContent, constants.aarch64FileName(newVersion)).then((hash) => { aarch64 = hash; }),
+    ];
+    await Promise.all(promises);
+    return { x86_64, aarch64 };
+}
+
+async function updateFile(newVersion, sha256Sums, currentFile) {
+    // There is some assumptions in how the file is formatted, but nothing egregious
+
+    let newFile = currentFile.replace(/version = "(.*)";/, `version = "${newVersion}";`);
+    newFile = newFile.replace(/x86_64-linux\.hash = "(.*)";/, `x86_64-linux.hash = "${sha256Sums.x86_64}";`);
+    newFile = newFile.replace(/aarch64-linux\.hash = "(.*)";/, `aarch64-linux.hash = "${sha256Sums.aarch64}";`);
+
+    await fs.writeFile('default.nix', newFile);
+};
+
+let currentFile = await fs.readFile('default.nix', 'utf8');
+let currentVersion = currentFile.match(/version = "(.*)";/)[1];
+const newVersion = await getLatestVersion();
+if (currentVersion === newVersion) {
+    console.error("Already up to date");
+    process.exit(0);
+}
+console.log("New version: " + newVersion);
+const sha256Sums = await getSha256Sums(newVersion);
+console.log(sha256Sums)
+if (!sha256Sums.x86_64 || !sha256Sums.aarch64) {
+    console.error("Failed to find sha256 sums for the 2 files");
+    process.exit(1);
+}
+updateFile(newVersion, sha256Sums, currentFile);