Create a modular Nix system to build FG42
This commit is contained in:
parent
1a0f2a31d2
commit
426c1d2dd1
|
@ -0,0 +1,219 @@
|
|||
# Fg42 - Emacs Editor for advance users
|
||||
#
|
||||
# Copyright (c) 2010-2024 Sameer Rahmani <lxsameer@gnu.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, version 2.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
{ lib
|
||||
, config
|
||||
, stdenv
|
||||
, git
|
||||
, texinfo
|
||||
, gcc
|
||||
, bash
|
||||
, utils
|
||||
, emacsPackagesFor
|
||||
, makeFontsConf
|
||||
, xorg
|
||||
, maintainers
|
||||
, writeText
|
||||
, writeShellApplication
|
||||
, ...
|
||||
}:
|
||||
|
||||
with builtins;
|
||||
let
|
||||
cfg = config.fg42;
|
||||
emacs = cfg.emacs;
|
||||
version = cfg.version;
|
||||
|
||||
emacsBundle = (emacsPackagesFor emacs).withPackages (_: cfg.elispPackages);
|
||||
|
||||
paths = map (x: "${x}/bin/") cfg.paths;
|
||||
pathsStr = lib.strings.concatStrings (lib.strings.intersperse ":" paths);
|
||||
|
||||
mimeTypes = builtins.concatStringsSep ";" cfg.mimeTypes;
|
||||
|
||||
fontsConf = makeFontsConf { fontDirectories = cfg.fonts; };
|
||||
|
||||
# Whatever that needs to be in the PATH is considered a runtime
|
||||
# dependency.
|
||||
# Fonts are obviously runtime dependency as well
|
||||
runtimeDependencies = cfg.paths ++ cfg.fonts ++ cfg.elispPackages;
|
||||
|
||||
buildConfig = generateBuildConfig cfg.buildConfig;
|
||||
|
||||
addToList = epkg: ''(add-to-list 'directories-to-autogen "${epkg}")'';
|
||||
|
||||
sexprs = [
|
||||
''
|
||||
(require 'loaddefs-gen)
|
||||
(defvar directories-to-autogen '())
|
||||
(defvar output-file (getenv "LOADEF_OUTPUT"))
|
||||
''
|
||||
] ++ (map addToList cfg.elispPackages) ++ [
|
||||
''
|
||||
(message ">> %s ----- %s" directories-to-autogen output-file)
|
||||
(loaddefs-generate directories-to-autogen
|
||||
output-file)
|
||||
(provide 'loaddef-generator)
|
||||
''
|
||||
];
|
||||
loaddefGenerator = writeText "loaddef-generator.el" (concatStringsSep "\n" sexprs);
|
||||
loaddefScript = writeShellApplication {
|
||||
name = "loaddef";
|
||||
|
||||
text = ''
|
||||
#!${stdenv.shell}
|
||||
set +x
|
||||
LOADEF_OUTPUT="$1" ${emacsBundle}/bin/emacs -Q -q --batch -l ${loaddefGenerator}
|
||||
'';
|
||||
};
|
||||
|
||||
startupPackage = cfg.startUp;
|
||||
|
||||
|
||||
# elsipFiles = map (file: ) cfg.elispPackages;
|
||||
# nativeCompiler = epkgs: ''
|
||||
# emacs -L . --batch -f batch-native-compile ${elispFiles}
|
||||
# '';
|
||||
in
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
inherit version;
|
||||
pname = "FG42";
|
||||
|
||||
src = ../../.;
|
||||
|
||||
buildPhase = ''
|
||||
runHook preBuild
|
||||
|
||||
LISPDIR=$out/share/fg42/
|
||||
mkdir -p $out/bin
|
||||
mkdir -p $out/share/applications/
|
||||
|
||||
install -d $LISPDIR
|
||||
|
||||
cp -rv ${src}/share $out/
|
||||
cp -rv ${src}/snippets $LISPDIR/snippets
|
||||
cp "${fontsConf}" $LISPDIR/fonts.conf
|
||||
|
||||
chmod 755 $LISPDIR -R
|
||||
|
||||
export FONTCONFIG_FILE="$LISPDIR/fonts.conf"
|
||||
|
||||
cat >> $out/share/applications/FG42.desktop << EOF
|
||||
[Desktop Entry]
|
||||
Encoding=UTF-8
|
||||
Name=FG42
|
||||
GenericName=FG42
|
||||
Comment=The nix base Emacs bundle for advance users
|
||||
MimeType=${mimeTypes}
|
||||
Type=Application
|
||||
Terminal=false
|
||||
Categories=Development;TextEditor;
|
||||
StartupWMClass=FG42
|
||||
Exec=${placeholder "out"}/bin/fg42
|
||||
Icon=fg42
|
||||
Version=${version}
|
||||
EOF
|
||||
|
||||
cat >> $out/share/runtime_deps << EOF
|
||||
${lib.strings.concatLines runtimeDependencies}
|
||||
${emacsBundle}
|
||||
EOF
|
||||
|
||||
cd $LISPDIR
|
||||
#compile stuff
|
||||
cd -
|
||||
|
||||
cat >> $out/bin/fg42 << EOF
|
||||
#!${stdenv.shell}
|
||||
|
||||
export PATH=${pathsStr}:$PATH
|
||||
export FONTCONFIG_FILE="$LISPDIR/fonts.conf"
|
||||
|
||||
LIBRARY_PATH="\$(${stdenv.cc}/bin/cc -print-file-name=libgccjit.so):\$LIBRARY_PATH" \
|
||||
FG42_WM=fales ${emacsBundle}/bin/emacs \
|
||||
--name FG42 \
|
||||
-q --no-splash --title FG42 \
|
||||
-l ${cfg.startUp} "\$@"
|
||||
EOF
|
||||
chmod +x $out/bin/fg42
|
||||
|
||||
|
||||
LISPDIR=$out/share/fg42/lisp/
|
||||
mkdir -p $LISPDIR
|
||||
#emacs --batch -l package --eval "(package-generate-autoloads \"${pname}\" \"$LISPDIR\")"
|
||||
# ${loaddefScript}/bin/loaddef ${placeholder "out"}/share/fg42/lisp/loaddefs.el
|
||||
|
||||
runHook postBuild
|
||||
|
||||
cat >> $out/bin/fg42-wm << EOF
|
||||
#!${stdenv.shell}
|
||||
|
||||
export FG42_HOME=${placeholder "out"}/share/fg42/
|
||||
export FG42_EMACSD=~/.fg42/v4/emacs.d
|
||||
export FG42_USE_NIX=true;
|
||||
export PATH=${pathsStr}:\$PATH
|
||||
export FONTCONFIG_FILE="$LISPDIR/fonts.conf"
|
||||
|
||||
# Disable access control for the current user.
|
||||
${xorg.xhost}/bin/xhost +SI:localuser:\$USER
|
||||
|
||||
# Make Java applications aware this is a non-reparenting window manager.
|
||||
export _JAVA_AWT_WM_NONREPARENTING=1
|
||||
|
||||
# Set default cursor.
|
||||
xsetroot -cursor_name left_ptr
|
||||
|
||||
# Set keyboard repeat rate.
|
||||
xset r rate 400 30
|
||||
|
||||
# Uncomment the following block to use the exwm-xim module.
|
||||
# export XMODIFIERS=@im=exwm-xim
|
||||
# export GTK_IM_MODULE=xim
|
||||
# export QT_IM_MODULE=xim
|
||||
# export CLUTTER_IM_MODULE=xim
|
||||
|
||||
LIBRARY_PATH="\$(${stdenv.cc}/bin/cc -print-file-name=libgccjit.so):\$LIBRARY_PATH" \
|
||||
FG42_WM=true ${emacsBundle}/bin/emacs \
|
||||
--name FG42 \
|
||||
-q --no-splash --title FG42 \
|
||||
-l \$FG42_HOME/lisp/fg42/fg42.el "\$@"
|
||||
EOF
|
||||
chmod +x $out/bin/fg42-wm
|
||||
|
||||
|
||||
runHook postBuild
|
||||
'';
|
||||
|
||||
buildInputs = [ emacs emacsBundle git texinfo gcc bash ];
|
||||
|
||||
addEmacsNativeLoadPath = true;
|
||||
|
||||
meta = {
|
||||
broken = false;
|
||||
platforms = emacs.meta.platforms;
|
||||
homepage = "https://fg42.org/";
|
||||
maintainers = [ maintainers.lxsameer ];
|
||||
description = "The mighty editor for the Emacsians";
|
||||
longDescription = ''
|
||||
FG42 is a framework to create and editor and window manager based on GNU/Emacs.
|
||||
It has a pre-defined setup as well which can be installed out of the box. But the
|
||||
goal of this project is to provide the API necessary to create an integrated editor.
|
||||
|
||||
So you need to know about Emacs in advance.
|
||||
'';
|
||||
license = lib.licenses.gpl3Plus;
|
||||
};
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
lxsameer@majin.69922:1712871165
|
|
@ -30,14 +30,20 @@ let
|
|||
lib = lib;
|
||||
};
|
||||
|
||||
|
||||
utils = pkgs.callPackage ./utils.nix { };
|
||||
|
||||
unitModule = import ./unit.nix { inherit pkgs lib; };
|
||||
final = lib.evalModules {
|
||||
modules = [ unitModule ] ++ fg42Modules ++ extraModules;
|
||||
specialArgs = {
|
||||
inherit utils;
|
||||
inherit (utils) makeFG42Drv;
|
||||
};
|
||||
};
|
||||
|
||||
in
|
||||
pkgs.callPackage ./derivation.nix {
|
||||
inherit (final) config options;
|
||||
inherit utils;
|
||||
maintainers = import ../maintainers.nix;
|
||||
utils = pkgs.callPackage ./utils.nix { };
|
||||
}
|
||||
|
|
|
@ -25,8 +25,11 @@
|
|||
, makeFontsConf
|
||||
, xorg
|
||||
, maintainers
|
||||
, writeText
|
||||
, writeShellApplication
|
||||
, ...
|
||||
}:
|
||||
|
||||
with builtins;
|
||||
let
|
||||
cfg = config.fg42;
|
||||
|
@ -42,8 +45,49 @@ let
|
|||
|
||||
fontsConf = makeFontsConf { fontDirectories = cfg.fonts; };
|
||||
|
||||
# Whatever that needs to be in the PATH is considered a runtime
|
||||
# dependency.
|
||||
# Fonts are obviously runtime dependency as well
|
||||
runtimeDependencies = cfg.paths ++ cfg.fonts ++ cfg.elispPackages;
|
||||
|
||||
buildConfig = generateBuildConfig cfg.buildConfig;
|
||||
|
||||
addToList = epkg: ''(add-to-list 'directories-to-autogen "${epkg}")'';
|
||||
|
||||
sexprs = [
|
||||
''
|
||||
(require 'loaddefs-gen)
|
||||
(defvar directories-to-autogen '())
|
||||
(defvar output-file (getenv "LOADEF_OUTPUT"))
|
||||
''
|
||||
] ++ (map addToList cfg.elispPackages) ++ [
|
||||
''
|
||||
(message ">> %s ----- %s" directories-to-autogen output-file)
|
||||
(loaddefs-generate directories-to-autogen
|
||||
output-file)
|
||||
(provide 'loaddef-generator)
|
||||
''
|
||||
];
|
||||
loaddefGenerator = writeText "loaddef-generator.el" (concatStringsSep "\n" sexprs);
|
||||
loaddefScript = writeShellApplication {
|
||||
name = "loaddef";
|
||||
|
||||
text = ''
|
||||
#!${stdenv.shell}
|
||||
set +x
|
||||
LOADEF_OUTPUT="$1" ${emacsBundle}/bin/emacs -Q -q --batch -l ${loaddefGenerator}
|
||||
'';
|
||||
};
|
||||
|
||||
startupPackage = cfg.startUp;
|
||||
|
||||
|
||||
# elsipFiles = map (file: ) cfg.elispPackages;
|
||||
# nativeCompiler = epkgs: ''
|
||||
# emacs -L . --batch -f batch-native-compile ${elispFiles}
|
||||
# '';
|
||||
in
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
inherit version;
|
||||
pname = "FG42";
|
||||
|
@ -51,13 +95,15 @@ stdenv.mkDerivation rec {
|
|||
src = ../../.;
|
||||
|
||||
buildPhase = ''
|
||||
runHook preBuild
|
||||
|
||||
LISPDIR=$out/share/fg42/
|
||||
mkdir -p $out/bin
|
||||
mkdir -p $out/share/applications/
|
||||
|
||||
install -d $LISPDIR
|
||||
|
||||
cp -rv ${src}/lisp/ $LISPDIR
|
||||
# cp -rv ${src}/lisp/ $LISPDIR
|
||||
|
||||
cp -rv ${src}/share $out/
|
||||
cp -rv ${src}/snippets $LISPDIR/snippets
|
||||
|
@ -83,18 +129,18 @@ stdenv.mkDerivation rec {
|
|||
Version=${version}
|
||||
EOF
|
||||
|
||||
runHook preBuild
|
||||
cat >> $out/share/runtime_deps << EOF
|
||||
${lib.strings.concatLines runtimeDependencies}
|
||||
${emacsBundle}
|
||||
EOF
|
||||
|
||||
cd $LISPDIR
|
||||
emacs -L . --batch -f batch-byte-compile *.el
|
||||
#compile stuff
|
||||
cd -
|
||||
|
||||
cat >> $out/bin/fg42 << EOF
|
||||
#!${stdenv.shell}
|
||||
|
||||
export FG42_HOME=${placeholder "out"}/share/fg42/
|
||||
export FG42_EMACSD=~/.fg42/v4/emacs.d
|
||||
export FG42_USE_NIX=true;
|
||||
export PATH=${pathsStr}:$PATH
|
||||
export FONTCONFIG_FILE="$LISPDIR/fonts.conf"
|
||||
|
||||
|
@ -102,9 +148,16 @@ stdenv.mkDerivation rec {
|
|||
FG42_WM=fales ${emacsBundle}/bin/emacs \
|
||||
--name FG42 \
|
||||
-q --no-splash --title FG42 \
|
||||
-l \$FG42_HOME/lisp/fg42/init.el "\$@"
|
||||
-l ${cfg.startUp} "\$@"
|
||||
EOF
|
||||
chmod +x $out/bin/fg42
|
||||
|
||||
|
||||
LISPDIR=$out/share/fg42/lisp/
|
||||
mkdir -p $LISPDIR
|
||||
#emacs --batch -l package --eval "(package-generate-autoloads \"${pname}\" \"$LISPDIR\")"
|
||||
# ${loaddefScript}/bin/loaddef ${placeholder "out"}/share/fg42/lisp/loaddefs.el
|
||||
|
||||
runHook postBuild
|
||||
|
||||
cat >> $out/bin/fg42-wm << EOF
|
||||
|
@ -137,23 +190,15 @@ stdenv.mkDerivation rec {
|
|||
LIBRARY_PATH="\$(${stdenv.cc}/bin/cc -print-file-name=libgccjit.so):\$LIBRARY_PATH" \
|
||||
FG42_WM=true ${emacsBundle}/bin/emacs \
|
||||
--name FG42 \
|
||||
-q --no-splash --title FG42 \
|
||||
-l \$FG42_HOME/lisp/fg42/init.el "\$@"
|
||||
-q --no-splash --title FG42 \
|
||||
-l \$FG42_HOME/lisp/fg42/fg42.el "\$@"
|
||||
EOF
|
||||
chmod +x $out/bin/fg42-wm
|
||||
|
||||
LISPDIR=$out/share/fg42/lisp/
|
||||
emacs --batch -l package --eval "(package-generate-autoloads \"${pname}\" \"$LISPDIR\")"
|
||||
|
||||
runHook postBuild
|
||||
'';
|
||||
|
||||
# installPhase = ''
|
||||
# runHook preInstall
|
||||
|
||||
# runHook postInstall
|
||||
# '';
|
||||
|
||||
buildInputs = [ emacs emacsBundle git texinfo gcc bash ];
|
||||
|
||||
addEmacsNativeLoadPath = true;
|
||||
|
|
|
@ -59,7 +59,6 @@ with lib;
|
|||
A list of mineType strings that FG42 should handle via
|
||||
desktop file.
|
||||
'';
|
||||
|
||||
};
|
||||
|
||||
fg42.fonts = mkOption {
|
||||
|
@ -69,6 +68,12 @@ with lib;
|
|||
A list of font packages that should be included in FG42
|
||||
'';
|
||||
};
|
||||
|
||||
fg42.startUp = mkOption {
|
||||
type = types.uniq types.path;
|
||||
description = "The main startup file to load first. This is usually fg42.el";
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -13,7 +13,26 @@
|
|||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
{ ... }:
|
||||
{ emacsPackages, writeTextFile, ... }:
|
||||
{
|
||||
makeDesktopFile = { };
|
||||
|
||||
makeFG42Drv = { pname, version, ... }@args:
|
||||
(emacsPackages.trivialBuild args).overrideAttrs (old: {
|
||||
pname = "fg42-${pname}";
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
|
||||
LISPDIR=$out/share/emacs/
|
||||
install -d $LISPDIR
|
||||
cp -rv lisp/ $LISPDIR/site-lisp
|
||||
|
||||
emacs --batch -l package --eval "(package-generate-autoloads \"${args.pname}\" \"$LISPDIR/site-lisp\")"
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
# Fg42 - Emacs Editor for advance users
|
||||
#
|
||||
# Copyright (c) 2010-2024 Sameer Rahmani <lxsameer@gnu.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, version 2.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# This is the home manager module that exposes FG42. It differs
|
||||
# from FG42 modules that are structurally the same but used in
|
||||
# different context
|
||||
|
||||
# A list of default FG42 modules to build FG42 with.
|
||||
{ lib, config, pkgs, ... }:
|
||||
with lib;
|
||||
let
|
||||
generateBuildConfig = configs:
|
||||
let
|
||||
defineConfig = cs: name:
|
||||
let
|
||||
config = builtins.getAttr name cs;
|
||||
form = if config.const then "defconst" else "defvar";
|
||||
in
|
||||
''(${form} ${name} ${config.value} "${config.docs}")'';
|
||||
|
||||
configsList = builtins.map (defineConfig configs) (builtins.attrNames configs);
|
||||
|
||||
in
|
||||
pkgs.writeTextFile {
|
||||
name = "build-config";
|
||||
text = ''
|
||||
${builtins.concatStringsSep "\n" configsList}
|
||||
(provide 'fg42/build-config)
|
||||
'';
|
||||
executable = false;
|
||||
};
|
||||
|
||||
buildConfig = generateBuildConfig (config.fg42.buildConfig);
|
||||
drv = pkgs.emacsPackages.trivialBuild rec {
|
||||
pname = "fg42-build-config";
|
||||
version = config.fg42.version;
|
||||
src = ./.;
|
||||
|
||||
buildPhase = ''
|
||||
runHook preBuild
|
||||
|
||||
LISPDIR=$out/share/emacs/site-lisp/fg42
|
||||
install -d $LISPDIR
|
||||
|
||||
cp -v ${buildConfig} $LISPDIR/build-config.el
|
||||
|
||||
emacs -L . --batch -f batch-byte-compile *.el
|
||||
|
||||
runHook postBuild
|
||||
'';
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
|
||||
LISPDIR=$out/share/emacs/site-lisp/fg42/
|
||||
emacs --batch -l package --eval "(package-generate-autoloads \"${pname}\" \"$LISPDIR\")"
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
};
|
||||
in
|
||||
{
|
||||
options = {
|
||||
fg42.buildConfig = mkOption {
|
||||
type = types.attrsOf
|
||||
(types.submodule {
|
||||
options = {
|
||||
value = mkOption {
|
||||
type = types.str;
|
||||
default = "nil";
|
||||
description = ''
|
||||
The value should be quoted. For example the string "nil"
|
||||
means the actual nil in elisp and the string "\"foo\""
|
||||
means elisp string "foo".
|
||||
'';
|
||||
};
|
||||
docs = mkOption {
|
||||
type = types.str;
|
||||
description = "The docstring for the variable or constant (mandatory)";
|
||||
};
|
||||
const = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "defvar vs defconst";
|
||||
};
|
||||
};
|
||||
});
|
||||
default = { };
|
||||
example = ''
|
||||
fg42.config = {
|
||||
"fg42/some-var" = {
|
||||
value = "foo";
|
||||
docs = "The docstring";
|
||||
const = false;
|
||||
};
|
||||
};
|
||||
'';
|
||||
description = ''
|
||||
An attrset of configuration variables and their values
|
||||
that should end up in `fg42/config` elisp module.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
config = {
|
||||
fg42.elispPackages = [ drv ];
|
||||
};
|
||||
}
|
|
@ -22,7 +22,8 @@
|
|||
{ pkgs, lib }:
|
||||
let
|
||||
modules = [
|
||||
./editor.nix
|
||||
./build_config
|
||||
./editor
|
||||
];
|
||||
|
||||
pkgsModule = { config, ... }: {
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
# Fg42 - Emacs Editor for advance users
|
||||
#
|
||||
# Copyright (c) 2010-2024 Sameer Rahmani <lxsameer@gnu.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, version 2.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# This is the home manager module that exposes FG42. It differs
|
||||
# from FG42 modules that are structurally the same but used in
|
||||
# different context
|
||||
|
||||
# A list of default FG42 modules to build FG42 with.
|
||||
{ lib, ... }:
|
||||
{
|
||||
options = {
|
||||
fg42.editor = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "blah";
|
||||
description = ''
|
||||
FG42's version1.
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
# Fg42 - Emacs Editor for advance users
|
||||
#
|
||||
# Copyright (c) 2010-2024 Sameer Rahmani <lxsameer@gnu.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, version 2.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# This is the home manager module that exposes FG42. It differs
|
||||
# from FG42 modules that are structurally the same but used in
|
||||
# different context
|
||||
|
||||
# A list of default FG42 modules to build FG42 with.
|
||||
{ lib, config, pkgs, makeFG42Drv, ... }:
|
||||
let
|
||||
deps = (with pkgs.emacsPackages; [
|
||||
origami
|
||||
which-key
|
||||
projectile
|
||||
projectile-ripgrep
|
||||
pkg-info
|
||||
expand-region
|
||||
helpful
|
||||
envrc
|
||||
pinentry
|
||||
discover
|
||||
exec-path-from-shell
|
||||
avy
|
||||
ace-window
|
||||
yasnippet
|
||||
yasnippet-snippets
|
||||
flycheck
|
||||
]);
|
||||
drv = makeFG42Drv {
|
||||
pname = "fg42-editor";
|
||||
version = config.fg42.version;
|
||||
buildInputs = deps;
|
||||
src = ./.;
|
||||
};
|
||||
|
||||
dicts = pkgs.aspellWithDicts (dicts: with dicts; [ en en-computers en-science ]);
|
||||
in
|
||||
{
|
||||
|
||||
config = {
|
||||
fg42.elispPackages = [ drv ] ++ deps;
|
||||
fg42.startUp = lib.mkDefault "${drv}/share/emacs/site-lisp/fg42.el";
|
||||
|
||||
fg42.fonts = (with pkgs;[
|
||||
vazir-fonts
|
||||
fira-code
|
||||
fira-mono
|
||||
noto-fonts
|
||||
]);
|
||||
|
||||
fg42.paths = (with pkgs;[
|
||||
ripgrep
|
||||
dicts
|
||||
]);
|
||||
|
||||
fg42.buildConfig = {
|
||||
"fg42/font" = {
|
||||
value = '''("Fira Mono" 11)'';
|
||||
docs = ''
|
||||
The default font for FG42. You can override it
|
||||
in your configuration file.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,166 @@
|
|||
;;; FG42 --- The mighty editor for the emacsians -*- lexical-binding: t; -*-
|
||||
;;
|
||||
;; Copyright (c) 2010-2024 Sameer Rahmani <lxsameer@gnu.org>
|
||||
;;
|
||||
;; Author: Sameer Rahmani <lxsameer@gnu.org>
|
||||
;; URL: https://devheroes.codes/FG42/FG42
|
||||
;; Version: 4.0.0
|
||||
;;
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
;;
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
;;
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
;;
|
||||
;;; Commentary:
|
||||
;;; Code:
|
||||
(require 'fg42/utils)
|
||||
(eval-when-compile
|
||||
(defvar package-archives)
|
||||
(defvar use-package-ensure-function))
|
||||
|
||||
;; ============================================================================
|
||||
;; Basic inital configuration for FG42's operations
|
||||
;; ============================================================================
|
||||
(defgroup fg42 nil
|
||||
"Customize your FG42 instance via this group of configurations."
|
||||
:group :editor)
|
||||
|
||||
(defvar fg42/disabled-features nil
|
||||
"List of features to disable.")
|
||||
|
||||
(defvar fg42/after-init-hook nil
|
||||
"The hook tha runs when FG42 finished running the user configuration.")
|
||||
|
||||
(defvar fg42/debug? nil
|
||||
"It is t If FG42 is running in debug mode and nil otherwise.")
|
||||
|
||||
(defvar fg42/-gc-cons-threshold 16777216
|
||||
"Value of GC threshold of FG42.")
|
||||
|
||||
(defvar fg42/initialized nil
|
||||
"A variable that indicates whether FG42 is passed initialization.")
|
||||
|
||||
|
||||
(defconst fg42/cache-dir (or (getenv "FG42_CACHE_DIR")
|
||||
(path-join (or (getenv "XDG_CACHE_HOME") "~/.cache")
|
||||
"fg42")))
|
||||
|
||||
|
||||
(defconst fg42/config-dir (or (getenv "FG42_CONFIG_DIR")
|
||||
(path-join (or (getenv "XDG_CONFIG_HOME") "~/.config")
|
||||
"fg42")))
|
||||
|
||||
|
||||
(defun defer-garbage-collection ()
|
||||
"Disable garbage collection."
|
||||
(setq gc-cons-threshold fg42/-gc-cons-threshold))
|
||||
|
||||
|
||||
(defun restore-garbage-collection ()
|
||||
"Restore garbage collection to it's default value."
|
||||
(run-at-time
|
||||
1 nil (lambda () (setq gc-cons-threshold most-positive-fixnum))))
|
||||
|
||||
|
||||
(defun fg42/-startup-optimization ()
|
||||
"Optimized FG42 startup."
|
||||
;; by setting gc threshold to the largest number
|
||||
;; Emacs can understand we are basically disabling it :).
|
||||
(setq gc-cons-threshold most-positive-fixnum
|
||||
gc-cons-percentage 0.6)
|
||||
;; after initilization phase restore cons threshold to normal
|
||||
(add-hook 'emacs-startup-hook
|
||||
(lambda ()
|
||||
(setq gc-cons-threshold fg42/-gc-cons-threshold ; 16mb
|
||||
gc-cons-percentage 0.1)))
|
||||
|
||||
;; disable gc when we are in minibuffer using the same method we
|
||||
;; use for initilization time
|
||||
(add-hook 'minibuffer-setup-hook #'defer-garbage-collection)
|
||||
;; just enable gc when exiting minibuffer
|
||||
(add-hook 'minibuffer-exit-hook #'restore-garbage-collection)
|
||||
;; we dont need Emacs to check every file type and look for file
|
||||
;; handlers when we are initializing so we backup the original
|
||||
;; value and set it to nil
|
||||
(setq --file-name-handler-alist file-name-handler-alist)
|
||||
|
||||
(setq file-name-handler-alist nil)
|
||||
;; after initialization we can restore that file-name-handler-alist
|
||||
;; to original value.
|
||||
(add-hook 'emacs-startup-hook
|
||||
(lambda ()
|
||||
(setq file-name-handler-alist
|
||||
--file-name-handler-alist)))
|
||||
;; initial mode for emacs can be fundamental mode we have nothing to lose
|
||||
(setq initial-major-mode 'fundamental-mode))
|
||||
|
||||
|
||||
(defun fg42/initialize ()
|
||||
"Initialize FG42 after the Emacs window is rendered by loading the user init file."
|
||||
;; (fg42/-startup-optimization)
|
||||
(require 'fg42/editor)
|
||||
|
||||
(when (file-exists-p user-init-file)
|
||||
(load user-init-file))
|
||||
|
||||
(fg42/setup-editor)
|
||||
;; ;; If user didn't select a theme, load the default stuff
|
||||
;; (when (not (featurep 'fg42/themes))
|
||||
;; (require 'fg42/themes))
|
||||
|
||||
(add-hook 'emacs-startup-hook
|
||||
(lambda ()
|
||||
(run-hooks 'fg42/after-init-hook)
|
||||
(run-hooks 'fg42/ui-hook)
|
||||
(setq fg42/initialized t))))
|
||||
|
||||
|
||||
(defun fg42/main ()
|
||||
"The entry point of FG42."
|
||||
(when (string= (getenv "FG42_DEBUG") "1")
|
||||
(setq debug-on-error t
|
||||
fg42/debug? t))
|
||||
|
||||
;; We don't use any Emacs package manager, so
|
||||
;; prevent package.el to install anything at startup
|
||||
(setq package-enable-at-startup nil
|
||||
package-archives nil
|
||||
use-package-ensure-function 'ignore
|
||||
|
||||
;; Setup the path for the custom.el file, We don't want
|
||||
;; to touch user's Emacs configuration.
|
||||
custom-file (path-join fg42/config-dir "custom.el")
|
||||
|
||||
;; Change the config dir to `~/.config/fg42/' by default
|
||||
;; again, we don't want to temper with user's Emacs
|
||||
user-emacs-directory fg42/config-dir
|
||||
user-init-file
|
||||
(or (getenv "FG42_CONFIG_FILE")
|
||||
(path-join fg42/config-dir "fg42.el")))
|
||||
|
||||
;; Change the eln file cache to leave Emacs alone.
|
||||
(startup-redirect-eln-cache
|
||||
(or (getenv "FG42_ELN_DIR")
|
||||
(path-join fg42/cache-dir "fg42.el")))
|
||||
|
||||
;; Load the customization file. In FG42 it is different than
|
||||
;; the default `user-init-file'
|
||||
(if (file-exists-p custom-file)
|
||||
(load custom-file))
|
||||
|
||||
;; From point forward we can use normal Elisp stuff without
|
||||
;; interfering with user's Emacs configuration
|
||||
(fg42/initialize))
|
||||
|
||||
(fg42/main)
|
||||
|
||||
(provide 'fg42)
|
||||
;;; fg42.el ends here
|
|
@ -0,0 +1,293 @@
|
|||
;;; FG42 --- The mighty editor for the emacsians -*- lexical-binding: t; -*-
|
||||
;;
|
||||
;; Copyright (c) 2010-2024 Sameer Rahmani & Contributors
|
||||
;;
|
||||
;; Author: Sameer Rahmani <lxsameer@gnu.org>
|
||||
;; URL: https://devheroes.codes/FG42/FG42
|
||||
;; Version: 4.0.0
|
||||
;;
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
;;
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
;;
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
;;
|
||||
;;; Commentary:
|
||||
;;; Code:
|
||||
(eval-when-compile
|
||||
(require 'fpkg)
|
||||
;; We build this file via the main FG42's Nix derivation. It
|
||||
;; contains the final Nix configuration of FG42.
|
||||
(require 'fg42/build-config)
|
||||
;; ;; Language support
|
||||
;; (require 'fg42/autocomplete)
|
||||
;; (require 'fg42/langs/langs)
|
||||
;; (require 'fg42/eglot)
|
||||
;; (require 'fg42/langs/cpp)
|
||||
;; (require 'fg42/langs/verilog)
|
||||
;; (require 'fg42/langs/python)
|
||||
;; (require 'fg42/langs/elisp)
|
||||
;; (require 'fg42/langs/nix)
|
||||
|
||||
;; (require 'fg42/git)
|
||||
;; (require 'fg42/wm)
|
||||
;; (require 'fg42/org)
|
||||
;; (require 'fg42/minibuffer)
|
||||
;; (require 'fg42/graphics)
|
||||
;; (require 'fg42/modeline)
|
||||
)
|
||||
|
||||
(require 'server)
|
||||
(require 'fg42/utils)
|
||||
|
||||
|
||||
(defun fg42/setup-font ()
|
||||
"Set the default font of `FG42' to FONT-NAME and FONT-SIZE."
|
||||
(let ((name (car fg42/font))
|
||||
(size (cadr fg42/font)))
|
||||
(add-to-list 'default-frame-alist
|
||||
(cons 'font (format "%s-%d" name size)))
|
||||
|
||||
(set-face-attribute 'default t :font name)))
|
||||
|
||||
|
||||
|
||||
(defun fg42/setup-editor ()
|
||||
"Setup the overall functionality of FG42."
|
||||
|
||||
(use! origami
|
||||
"A text folding minor mode for Emacs."
|
||||
:bind
|
||||
(("C-c TAB" . origami-toggle-node))
|
||||
:config
|
||||
(global-origami-mode t))
|
||||
|
||||
(use! which-key
|
||||
"which-key is a minor mode for Emacs that displays the key bindings following
|
||||
your currently entered incomplete command (a prefix) in a popup. For example,
|
||||
after enabling the minor mode if you enter ~C-x~ and wait for the default of
|
||||
1 second the minibuffer will expand with all of the available key bindings
|
||||
that follow ~C-x~ (or as many as space allows given your settings).
|
||||
This includes prefixes like ~C-x 8~ which are shown in a different face."
|
||||
:config
|
||||
(which-key-setup-side-window-bottom)
|
||||
(which-key-mode))
|
||||
|
||||
(use! projectile
|
||||
"Projectile is a project interaction library for Emacs. Its goal is to provide
|
||||
a nice set of features operating on a project level without introducing
|
||||
external dependencies."
|
||||
:hook (emacs-startup . projectile-mode)
|
||||
:config
|
||||
;; We don't want the auto discovery on startup
|
||||
(setq projectile-auto-discover nil)
|
||||
(setq projectile-enable-caching t)
|
||||
|
||||
:bind (:map projectile-mode-map
|
||||
("s-p" . projectile-command-map)
|
||||
("C-c p" . projectile-command-map)))
|
||||
|
||||
|
||||
(use! projectile-ripgrep
|
||||
"Use ripgrep with projectile"
|
||||
:after projectile)
|
||||
|
||||
|
||||
(use! pkg-info
|
||||
"`pkg-info' integration.")
|
||||
|
||||
|
||||
(use! expand-region
|
||||
"Expand region increases the selected region by semantic units.
|
||||
Just keep pressing the key until it selects what you want."
|
||||
:bind ("C-=" . er/expand-region))
|
||||
|
||||
|
||||
(use! helpful
|
||||
"Helpful is an alternative to the built-in Emacs help that provides much more
|
||||
contextual information."
|
||||
:bind
|
||||
(("C-h f" . helpful-callable)
|
||||
("C-h v" . helpful-variable)
|
||||
("C-h k" . helpful-key)
|
||||
("C-h x" . helpful-command)
|
||||
("C-c C-d" . helpful-at-point)))
|
||||
|
||||
(use! envrc
|
||||
"Activate direnv whenever encounter a `.envrc' file"
|
||||
:config
|
||||
(envrc-global-mode))
|
||||
|
||||
(use! pinentry
|
||||
"Pinentry cube with setup the =pinentry= program to be used within FG42."
|
||||
:commands pinentry-start
|
||||
:init
|
||||
(setq epa-pinentry-mode 'loopback))
|
||||
|
||||
(use! imenu-list
|
||||
"his Emacs minor-mode creates an automatically updated buffer
|
||||
called `Ilist' that is populated with the current buffer's imenu entries.
|
||||
The `Ilist' buffer is typically shown as a sidebar (Emacs vertically splits the window)."
|
||||
:bind (("C-'" . imenu-list-smart-toggle)))
|
||||
|
||||
(use! discover
|
||||
"Adds support for the discover.el `https://github.com/mickeynp/discover.el'.")
|
||||
|
||||
(use! exec-path-from-shell
|
||||
"This package fixes the =exec-path-from-shell= issue on MacOS."
|
||||
:config
|
||||
(when (memq window-system '(mac ns x))
|
||||
(exec-path-from-shell-initialize)))
|
||||
|
||||
(use! hl-line
|
||||
"Highlights the current line."
|
||||
:hook (emacs-startup . global-hl-line-mode))
|
||||
|
||||
(use! avy
|
||||
"This cube controls the different aspect of buffer navigation"
|
||||
:bind ("M-1" . avy-goto-word-1))
|
||||
|
||||
(use! ace-window
|
||||
"This cube controls the different aspect of buffer navigation"
|
||||
:bind ("C-<tab>" . ace-window))
|
||||
|
||||
(when-not-wm
|
||||
|
||||
(use! flyspell
|
||||
"Spell checking on the fly"
|
||||
:commands (flyspell-mode flyspell-prog-mode)
|
||||
:init
|
||||
(setq-default ispell-program-name "aspell")
|
||||
(setq-default ispell-extra-args '("--sug-mode=ultra"
|
||||
"--lang=en_US"
|
||||
"--camel-case")))
|
||||
|
||||
(use! savehist
|
||||
"Persist history over Emacs restarts. Vertico sorts by history position."
|
||||
:init
|
||||
(savehist-mode))
|
||||
|
||||
(use! display-line-numbers
|
||||
"The builtin replacement of linum. It's is pretty fast."
|
||||
:config
|
||||
(global-display-line-numbers-mode 1)))
|
||||
|
||||
|
||||
(use! yasnippet
|
||||
"A Snippet is a template system for Emacs. "
|
||||
:config
|
||||
(let* ((snippet-home
|
||||
(path-join
|
||||
(file-name-directory
|
||||
(locate-library "yasnippet-snippets")) "snippets"))
|
||||
(local-snippet (path-join (file-name-directory
|
||||
(locate-library "fg42")) "../snippets"))
|
||||
(user-snippets (path-join fg42/config-dir "snippets")))
|
||||
|
||||
(setq yas-snippet-dirs `(,user-snippets ,local-snippet ,snippet-home))
|
||||
(yas-global-mode 1)))
|
||||
|
||||
(use! yasnippet-snippets
|
||||
"Yasnippet's snippets."
|
||||
:after yasnippet)
|
||||
|
||||
|
||||
(use! flycheck
|
||||
"Flycheck is a modern on-the-fly syntax checking extension for GNU Emacs."
|
||||
:config (global-flycheck-mode))
|
||||
|
||||
;; In the following section we're setting some default behavior of FG42.
|
||||
;; Most of these configuration are opiniated and I think most of people
|
||||
;; shared the same opinion or don't care at all.
|
||||
(fg42/setup-font)
|
||||
(add-hook 'fg42/after-init-hook
|
||||
(lambda ()
|
||||
(set-default 'cursor-type 'bar)
|
||||
(set-cursor-color "#eeeeec")))
|
||||
|
||||
;; Remove splash screen
|
||||
(setq inhibit-splash-screen t)
|
||||
;; scratch should be scratch
|
||||
(setq initial-scratch-message nil)
|
||||
;; Don't allow tab as indent
|
||||
(setq-default indent-tabs-mode nil)
|
||||
;; Default indent width
|
||||
(setq tab-width 2)
|
||||
;; Share the clipboard with X applications
|
||||
(setq x-select-enable-clipboard t)
|
||||
;; Automatically removed excess backups of the file
|
||||
(setq delete-old-versions t)
|
||||
;; Emacs 28 and newer: Hide commands in M-x which do not work in the current
|
||||
;; mode. Vertico commands are hidden in normal buffers. This setting is
|
||||
;; useful beyond Vertico.
|
||||
(setq read-extended-command-predicate #'command-completion-default-include-p)
|
||||
|
||||
;; Support opening new minibuffers from inside existing minibuffers.
|
||||
(setq enable-recursive-minibuffers t)
|
||||
|
||||
(setq tooltip-use-echo-area t)
|
||||
(setq x-gtk-use-system-tooltips nil)
|
||||
|
||||
;; Global configurations
|
||||
(tool-bar-mode -1)
|
||||
(tooltip-mode nil)
|
||||
(menu-bar-mode -1)
|
||||
|
||||
(when (display-graphic-p)
|
||||
;; Smoother scrolling
|
||||
(pixel-scroll-precision-mode)
|
||||
(scroll-bar-mode -1))
|
||||
|
||||
(defalias 'yes-or-no-p 'y-or-n-p)
|
||||
|
||||
;; Hooks ---
|
||||
(add-hook
|
||||
'emacs-startup-hook
|
||||
(lambda ()
|
||||
;; It only applies to toolkit=no
|
||||
(set-mouse-color (get-base16-color-or :base07 "#eeeeec"))
|
||||
|
||||
;; Switch from `dabbrev-expand' to `hippie-expand'
|
||||
(global-set-key [remap dabbrev-expand] 'hippie-expand)
|
||||
|
||||
(column-number-mode t)
|
||||
(show-paren-mode t)
|
||||
(electric-pair-mode 1)
|
||||
|
||||
;; Rectangular select
|
||||
(cua-selection-mode t)
|
||||
|
||||
;; Yank the region on type
|
||||
(delete-selection-mode 1)))
|
||||
|
||||
;; Deletel extra trailing white spaces on save
|
||||
(add-hook 'before-save-hook 'delete-trailing-whitespace)
|
||||
|
||||
;; Enable rainbow-delimiters for programming
|
||||
(add-hook 'prog-mode-hook #'rainbow-delimiters-mode)
|
||||
|
||||
;; With this section we will have two emacs server running
|
||||
;; this way we can interact with the wm via emacsclient as well
|
||||
(when (not (server-running-p))
|
||||
(when-wm
|
||||
(setq server-name "fg42-wm"))
|
||||
(server-start)
|
||||
(require 'org-protocol))
|
||||
|
||||
(when-wm
|
||||
;; Activating the WM mode
|
||||
(exwm-enable)
|
||||
(exwm-systemtray-enable)
|
||||
(exwm-randr-enable))
|
||||
(message "[FG42]: Use `fg42-help' to get help."))
|
||||
|
||||
|
||||
(provide 'fg42/editor)
|
||||
;;; editor.el ends here
|
|
@ -0,0 +1,161 @@
|
|||
;;; Utils --- Utils library of FG42 -*- lexical-binding: t; -*-
|
||||
;;
|
||||
;; Copyright (c) 2010-2024 Sameer Rahmani <lxsameer@gnu.org>
|
||||
;;
|
||||
;; Author: Sameer Rahmani <lxsameer@gnu.org>
|
||||
;; URL: https://devheroes.codes/FG42/FG42
|
||||
;; Version: 4.0.0
|
||||
;;
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
;;
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
;;
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
;;
|
||||
;;; Commentary:
|
||||
;; `System' is just a state monad which holds the state of the editor.
|
||||
;; Each system has to have a `start' function to start the setup process.
|
||||
;;
|
||||
;;; Code:
|
||||
(require 'cl-lib)
|
||||
|
||||
(autoload 'seq-partition "seq")
|
||||
(autoload 'cl-reduce "cl-seq")
|
||||
|
||||
|
||||
(defun buffer-mode (buffer-or-string)
|
||||
"Return the major mode associated with a the given BUFFER-OR-STRING."
|
||||
(with-current-buffer buffer-or-string
|
||||
major-mode))
|
||||
|
||||
|
||||
(defun ->buffer (buffer-name data &optional fn)
|
||||
"Insert the given DATA into the given buffer provided by BUFFER-NAME.
|
||||
|
||||
It will create a the buffer if it doesn't exist. It will call the given FN
|
||||
at the end in context of the buffer. This function accepts only one argument
|
||||
with is the buffer."
|
||||
(let ((buf (get-buffer-create buffer-name)))
|
||||
(with-current-buffer buf
|
||||
(insert data)
|
||||
(when fn
|
||||
(funcall fn buf)))))
|
||||
|
||||
|
||||
(defun ->str (&rest args)
|
||||
"Convert the given ARGS into string."
|
||||
(funcall #'pp-to-string args))
|
||||
|
||||
|
||||
(defmacro inspect-expression (&rest body)
|
||||
"Pretty prints the result of the given BODY."
|
||||
`(pp-display-expression ,@body (get-buffer-create fg42/inspect-buffer)))
|
||||
|
||||
|
||||
(defun inspect-data-append (data)
|
||||
"Append the given DATA to the inspection buffer with padding."
|
||||
;; TODO: Move 'fg42/inspect-buffer' to the somewhere propriate
|
||||
;; possiblly the system.
|
||||
(->buffer
|
||||
"fg42/inspect-buffer"
|
||||
(format
|
||||
"\n;; START ======================================================\n%s%s"
|
||||
(pp-to-string data)
|
||||
";; END.\n")))
|
||||
|
||||
|
||||
(defun apply-face (face-symbol text)
|
||||
"Apply the given FACE-SYMBOL to the given TEXT."
|
||||
(put-text-property 0 (length text) 'face face-symbol text))
|
||||
|
||||
|
||||
(defmacro comment (&rest _body)
|
||||
"A macro similar to Clojure's comment macro that ignore the BODY."
|
||||
(declare (indent 0))
|
||||
`nil)
|
||||
|
||||
|
||||
(defmacro debug-message (&rest params)
|
||||
"Print out the given PARAMS only if debug mode is on."
|
||||
(if debug-on-error
|
||||
`(message ,@params)
|
||||
nil))
|
||||
|
||||
|
||||
(defmacro deprecated (msg &rest form)
|
||||
"Mark the given FORM as deprecated with the given MSG."
|
||||
(declare (indent 0))
|
||||
`(progn
|
||||
(warn (format "[DEPRECATED]: %s" ,msg))
|
||||
,@form))
|
||||
|
||||
|
||||
(defun path-join (&rest paths)
|
||||
"Join the given PATHS."
|
||||
(apply #'concat
|
||||
(append
|
||||
(mapcar #'file-name-as-directory (butlast paths))
|
||||
(last paths))))
|
||||
|
||||
|
||||
(defmacro -> (x &optional form &rest more)
|
||||
"Thread the expr through the forms FORM and rest of form in MORE.
|
||||
Insert X as the second item in the first form, making a list of
|
||||
it if it is not a list already. If there are more forms, insert
|
||||
the first form as the second item in second form, etc."
|
||||
(declare (debug (form &rest [&or symbolp (sexp &rest form)])))
|
||||
(cond
|
||||
((null form) x)
|
||||
((null more) (if (listp form)
|
||||
`(,(car form) ,x ,@(cdr form))
|
||||
(list form x)))
|
||||
(:else `(-> (-> ,x ,form) ,@more))))
|
||||
|
||||
|
||||
(defmacro ->> (x &optional form &rest more)
|
||||
"Thread the expr through the forms FORM and the rest at MORE.
|
||||
Insert X as the last item in the first form, making a list of
|
||||
it if it is not a list already. If there are more forms, insert
|
||||
the first form as the
|
||||
last item in second form, etc."
|
||||
(declare (debug ->))
|
||||
(cond
|
||||
((null form) x)
|
||||
((null more) (if (listp form)
|
||||
`(,@form ,x)
|
||||
(list form x)))
|
||||
(:else `(->> (->> ,x ,form) ,@more))))
|
||||
|
||||
|
||||
(defmacro when-wm (&rest body)
|
||||
"Run the BODY only if in wm mode."
|
||||
(if (string= (getenv "FG42_WM") "true")
|
||||
`(progn ,@body)
|
||||
nil))
|
||||
|
||||
(defmacro when-not-wm (&rest body)
|
||||
"Run the BODY only if not in the wm mode."
|
||||
(if (not (string= (getenv "FG42_WM") "true"))
|
||||
`(progn ,@body)
|
||||
nil))
|
||||
|
||||
|
||||
(defun get-base16-color-or (color-name default)
|
||||
"Return the color for COLOR-NAME if a base16 theme is loade otherwise DEFAULT."
|
||||
(let* ((theme (car custom-enabled-themes))
|
||||
(theme-sym (intern (format "%s-theme-colors" theme))))
|
||||
|
||||
(if (boundp theme-sym)
|
||||
(or (eval `(plist-get ,theme-sym ,color-name)) default)
|
||||
default)))
|
||||
|
||||
|
||||
(provide 'fg42/utils)
|
||||
;;; utils.el ends here
|
|
@ -0,0 +1,69 @@
|
|||
;;; fpkg --- a simple package manager for FG42 -*- lexical-binding: t; -*-
|
||||
;;
|
||||
;; Copyright (C) 2010-2024 Sameer Rahmani <lxsameer@gnu.org>
|
||||
;;
|
||||
;; Author: Sameer Rahmani <lxsameer@gnu.org>
|
||||
;; Keywords: lisp fg42 IDE package manager
|
||||
;; Version: 1.0.0
|
||||
;;
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
;;
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
;;
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
;;
|
||||
;;; Commentary:
|
||||
;;
|
||||
;; Simple package manager for FG42
|
||||
;;
|
||||
;;; Code:
|
||||
(require 'map)
|
||||
|
||||
(defvar package-names ())
|
||||
|
||||
(eval-when-compile
|
||||
(defvar fg42/disabled-features '())
|
||||
(require 'use-package))
|
||||
|
||||
|
||||
(defun inject-params (args)
|
||||
"Inject required `use-package' params to ARGS if the key is missing."
|
||||
;; (if (member :defer args)
|
||||
;; (append '(:ensure nil) args)
|
||||
(append args '(:ensure nil)))
|
||||
|
||||
|
||||
(defmacro fpkg/use (pkg &rest details)
|
||||
"Install the given package DETAILS PKG via `use-package' and straight."
|
||||
(declare (indent defun))
|
||||
(if (and (listp details) (< 0 (length details)))
|
||||
(let ((p (inject-params details)))
|
||||
`(progn
|
||||
(use-package ,pkg ,@p)))
|
||||
`(progn
|
||||
(use-package ,pkg :defer t :ensure nil))))
|
||||
|
||||
|
||||
(defmacro use! (pkg docs &rest details)
|
||||
"Loading the given package DETAILS PKG via `use-package'.
|
||||
|
||||
DOCS is the documentation of the package."
|
||||
(declare (indent defun) (doc-string 2))
|
||||
|
||||
(when (not (stringp docs))
|
||||
(error "Missing docstring for '%s' package" pkg))
|
||||
|
||||
(let ((disabled (or (member pkg fg42/disabled-features) nil)))
|
||||
(when (not disabled)
|
||||
`(use-package ,pkg ,@details))))
|
||||
|
||||
|
||||
(provide 'fpkg)
|
||||
;;; fpkg.el ends here
|
Loading…
Reference in New Issue