diff --git a/nix/deps.nix b/nix/deps.nix index dcbdf3a..6d65e0e 100644 --- a/nix/deps.nix +++ b/nix/deps.nix @@ -13,14 +13,15 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . - { pkgs, lib, elispDepsFile }: with builtins; let reader = import ./elisp_reader.nix { inherit lib; }; elispAst = reader.fromElisp (builtins.readFile elispDepsFile); dependsOnForm = filter (x: head x == "depends-on") elispAst; - elispPkgs = if length dependsOnForm == 0 - then throw "Can't find the form 'depends-on' on 'deps.el'" - else tail (head dependsOnForm); -in elispPkgs + elispPkgs = + if length dependsOnForm == 0 + then throw "Can't find the form 'depends-on' on 'deps.el'" + else tail (head dependsOnForm); +in +elispPkgs diff --git a/nix/desktop.nix b/nix/desktop.nix deleted file mode 100644 index 1fca586..0000000 --- a/nix/desktop.nix +++ /dev/null @@ -1,33 +0,0 @@ -# Fg42 - Emacs Editor for advance users -# -# Copyright (c) 2010-2024 Sameer Rahmani -# -# 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 . -{ pkgs, fg42, version }: -{ - desktop = pkgs.writeText "FG42.desktop" '' -[Desktop Entry] -Encoding=UTF-8 -Name=FG42 -GenericName=FG42 -Comment=Emacs Editor for advance users -MimeType=text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-java;application/x-shellscript;text/x-c;text/x-c++;text/x-ruby;text/x-python;text/x-clojure;text/css;text/html;text/x-javascript; -Type=Application -Terminal=false -Categories=Development;TextEditor; -StartupWMClass=FG42 -Exec=${fg42} %F -Icon=fg42 -Version=${version} - ''; -} diff --git a/nix/elisp_reader.nix b/nix/elisp_reader.nix index f41cf8e..a1958c3 100644 --- a/nix/elisp_reader.nix +++ b/nix/elisp_reader.nix @@ -25,18 +25,18 @@ let # but only as far in as specified by maxLength. mkMatcher = regex: maxLength: string: - let - substr = substring 0 maxLength string; - matched = match regex substr; - in - if matched != null then head matched else null; + let + substr = substring 0 maxLength string; + matched = match regex substr; + in + if matched != null then head matched else null; removeStrings = stringsToRemove: string: let len = length stringsToRemove; listOfNullStrings = genList (const "") len; in - replaceStrings stringsToRemove listOfNullStrings string; + replaceStrings stringsToRemove listOfNullStrings string; # Split a string of elisp into individual tokens and add useful # metadata. @@ -73,7 +73,8 @@ let matchSymbol = let symbolChar = ''([^${notInSymbol}]|\\.)''; - in mkMatcher ''(${symbolChar}+)([${notInSymbol}]|$).*'' symbolMaxLength; + in + mkMatcher ''(${symbolChar}+)([${notInSymbol}]|$).*'' symbolMaxLength; maxTokenLength = foldl' max 0 [ commentMaxLength @@ -125,173 +126,174 @@ let dot = matchDot rest; symbol = matchSymbol rest; in - if state.skip > 0 then - state // { + if state.skip > 0 then + state // { + pos = state.pos + 1; + skip = state.skip - 1; + line = if char == "\n" then state.line + 1 else state.line; + } + else if char == "\n" then + let + mod = state.line / 1000; + newState = { pos = state.pos + 1; - skip = state.skip - 1; - line = if char == "\n" then state.line + 1 else state.line; - } - else if char == "\n" then - let - mod = state.line / 1000; - newState = { - pos = state.pos + 1; - line = state.line + 1; - inherit mod; - }; - in - state // ( - # Force evaluation of old state every 1000 lines. Nix - # doesn't have a modulo builtin, so we have to save - # the result of an integer division and compare - # between runs. - if mod > state.mod then - seq state.acc newState - else - newState - ) - else if elem char [ " " "\t" "\r" ] then - state // { - pos = state.pos + 1; - inherit (state) line; - } - else if char == ";" then - if comment != null then - state // { - pos = state.pos + 1; - skip = (stringLength comment) - 1; - } - else throw "Unrecognized token on line ${toString state.line}: ${rest}" - else if char == "(" then - state // { - acc = state.acc ++ [{ type = "openParen"; value = "("; inherit (state) line; }]; - pos = state.pos + 1; - } - else if char == ")" then - state // { - acc = state.acc ++ [{ type = "closeParen"; value = ")"; inherit (state) line; }]; - pos = state.pos + 1; - } - else if char == "[" then - state // { - acc = state.acc ++ [{ type = "openBracket"; value = "["; inherit (state) line; }]; - pos = state.pos + 1; - } - else if char == "]" then - state // { - acc = state.acc ++ [{ type = "closeBracket"; value = "]"; inherit (state) line; }]; - pos = state.pos + 1; - } - else if char == "'" then - state // { - acc = state.acc ++ [{ type = "quote"; value = "'"; inherit (state) line; }]; - pos = state.pos + 1; - } - else if char == ''"'' then - if string != null then - state // { - acc = state.acc ++ [{ type = "string"; value = string; inherit (state) line; }]; - pos = state.pos + 1; - skip = (stringLength string) - 1; - } - else throw "Unrecognized token on line ${toString state.line}: ${rest}" - else if char == "#" then - let nextChar = substring 1 1 rest; - in - if nextChar == "'" then - state // { - acc = state.acc ++ [{ type = "function"; value = "#'"; inherit (state) line; }]; - pos = state.pos + 1; - skip = 1; - } - else if nextChar == "&" then - if boolVector != null then - state // { - acc = state.acc ++ [{ type = "boolVector"; value = boolVector; inherit (state) line; }]; - pos = state.pos + 1; - skip = (stringLength boolVector) - 1; - } - else throw "Unrecognized token on line ${toString state.line}: ${rest}" - else if nextChar == "s" then - if substring 2 1 rest == "(" then - state // { - acc = state.acc ++ [{ type = "record"; value = "#s"; inherit (state) line; }]; - pos = state.pos + 1; - skip = 1; - } - else throw "List must follow #s in record on line ${toString state.line}: ${rest}" - else if nextChar == "[" then - state // { - acc = state.acc ++ [{ type = "byteCode"; value = "#"; inherit (state) line; }]; - pos = state.pos + 1; - } - else if nonBase10Integer != null then - state // { - acc = state.acc ++ [{ type = "nonBase10Integer"; value = nonBase10Integer; inherit (state) line; }]; - pos = state.pos + 1; - skip = (stringLength nonBase10Integer) - 1; - } - else throw "Unrecognized token on line ${toString state.line}: ${rest}" - else if elem char [ "+" "-" "." "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" ] then - if integer != null then - state // { - acc = state.acc ++ [{ type = "integer"; value = integer; inherit (state) line; }]; - pos = state.pos + 1; - skip = (stringLength integer) - 1; - } - else if float != null then - state // { - acc = state.acc ++ [{ type = "float"; value = float; inherit (state) line; }]; - pos = state.pos + 1; - skip = (stringLength float) - 1; - } - else if dot != null then - state // { - acc = state.acc ++ [{ type = "dot"; value = dot; inherit (state) line; }]; - pos = state.pos + 1; - skip = (stringLength dot) - 1; - } - else if symbol != null then - state // { - acc = state.acc ++ [{ type = "symbol"; value = symbol; inherit (state) line; }]; - pos = state.pos + 1; - skip = (stringLength symbol) - 1; - } - else throw "Unrecognized token on line ${toString state.line}: ${rest}" - else if char == "?" then - if character != null then - state // { - acc = state.acc ++ [{ type = "character"; value = character; inherit (state) line; }]; - pos = state.pos + 1; - skip = (stringLength character) - 1; - } - else throw "Unrecognized token on line ${toString state.line}: ${rest}" - else if char == "`" then - state // { - acc = state.acc ++ [{ type = "backquote"; value = "`"; inherit (state) line; }]; - pos = state.pos + 1; - } - else if char == "," then - if substring 1 1 rest == "@" then - state // { - acc = state.acc ++ [{ type = "slice"; value = ",@"; inherit (state) line; }]; - skip = 1; - pos = state.pos + 1; - } + line = state.line + 1; + inherit mod; + }; + in + state // ( + # Force evaluation of old state every 1000 lines. Nix + # doesn't have a modulo builtin, so we have to save + # the result of an integer division and compare + # between runs. + if mod > state.mod then + seq state.acc newState else + newState + ) + else if elem char [ " " "\t" "\r" ] then + state // { + pos = state.pos + 1; + inherit (state) line; + } + else if char == ";" then + if comment != null then + state // { + pos = state.pos + 1; + skip = (stringLength comment) - 1; + } + else throw "Unrecognized token on line ${toString state.line}: ${rest}" + else if char == "(" then + state // { + acc = state.acc ++ [{ type = "openParen"; value = "("; inherit (state) line; }]; + pos = state.pos + 1; + } + else if char == ")" then + state // { + acc = state.acc ++ [{ type = "closeParen"; value = ")"; inherit (state) line; }]; + pos = state.pos + 1; + } + else if char == "[" then + state // { + acc = state.acc ++ [{ type = "openBracket"; value = "["; inherit (state) line; }]; + pos = state.pos + 1; + } + else if char == "]" then + state // { + acc = state.acc ++ [{ type = "closeBracket"; value = "]"; inherit (state) line; }]; + pos = state.pos + 1; + } + else if char == "'" then + state // { + acc = state.acc ++ [{ type = "quote"; value = "'"; inherit (state) line; }]; + pos = state.pos + 1; + } + else if char == ''"'' then + if string != null then + state // { + acc = state.acc ++ [{ type = "string"; value = string; inherit (state) line; }]; + pos = state.pos + 1; + skip = (stringLength string) - 1; + } + else throw "Unrecognized token on line ${toString state.line}: ${rest}" + else if char == "#" then + let nextChar = substring 1 1 rest; + in + if nextChar == "'" then + state // { + acc = state.acc ++ [{ type = "function"; value = "#'"; inherit (state) line; }]; + pos = state.pos + 1; + skip = 1; + } + else if nextChar == "&" then + if boolVector != null then state // { - acc = state.acc ++ [{ type = "expand"; value = ","; inherit (state) line; }]; + acc = state.acc ++ [{ type = "boolVector"; value = boolVector; inherit (state) line; }]; pos = state.pos + 1; + skip = (stringLength boolVector) - 1; } + else throw "Unrecognized token on line ${toString state.line}: ${rest}" + else if nextChar == "s" then + if substring 2 1 rest == "(" then + state // { + acc = state.acc ++ [{ type = "record"; value = "#s"; inherit (state) line; }]; + pos = state.pos + 1; + skip = 1; + } + else throw "List must follow #s in record on line ${toString state.line}: ${rest}" + else if nextChar == "[" then + state // { + acc = state.acc ++ [{ type = "byteCode"; value = "#"; inherit (state) line; }]; + pos = state.pos + 1; + } + else if nonBase10Integer != null then + state // { + acc = state.acc ++ [{ type = "nonBase10Integer"; value = nonBase10Integer; inherit (state) line; }]; + pos = state.pos + 1; + skip = (stringLength nonBase10Integer) - 1; + } + else throw "Unrecognized token on line ${toString state.line}: ${rest}" + else if elem char [ "+" "-" "." "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" ] then + if integer != null then + state // { + acc = state.acc ++ [{ type = "integer"; value = integer; inherit (state) line; }]; + pos = state.pos + 1; + skip = (stringLength integer) - 1; + } + else if float != null then + state // { + acc = state.acc ++ [{ type = "float"; value = float; inherit (state) line; }]; + pos = state.pos + 1; + skip = (stringLength float) - 1; + } + else if dot != null then + state // { + acc = state.acc ++ [{ type = "dot"; value = dot; inherit (state) line; }]; + pos = state.pos + 1; + skip = (stringLength dot) - 1; + } else if symbol != null then state // { acc = state.acc ++ [{ type = "symbol"; value = symbol; inherit (state) line; }]; pos = state.pos + 1; skip = (stringLength symbol) - 1; } + else throw "Unrecognized token on line ${toString state.line}: ${rest}" + else if char == "?" then + if character != null then + state // { + acc = state.acc ++ [{ type = "character"; value = character; inherit (state) line; }]; + pos = state.pos + 1; + skip = (stringLength character) - 1; + } + else throw "Unrecognized token on line ${toString state.line}: ${rest}" + else if char == "`" then + state // { + acc = state.acc ++ [{ type = "backquote"; value = "`"; inherit (state) line; }]; + pos = state.pos + 1; + } + else if char == "," then + if substring 1 1 rest == "@" then + state // { + acc = state.acc ++ [{ type = "slice"; value = ",@"; inherit (state) line; }]; + skip = 1; + pos = state.pos + 1; + } else - throw "Unrecognized token on line ${toString state.line}: ${rest}"; - in (builtins.foldl' readToken { acc = []; pos = 0; skip = 0; line = startLineNumber; mod = 0; } (stringToCharacters elisp)).acc; + state // { + acc = state.acc ++ [{ type = "expand"; value = ","; inherit (state) line; }]; + pos = state.pos + 1; + } + else if symbol != null then + state // { + acc = state.acc ++ [{ type = "symbol"; value = symbol; inherit (state) line; }]; + pos = state.pos + 1; + skip = (stringLength symbol) - 1; + } + else + throw "Unrecognized token on line ${toString state.line}: ${rest}"; + in + (builtins.foldl' readToken { acc = [ ]; pos = 0; skip = 0; line = startLineNumber; mod = 0; } (stringToCharacters elisp)).acc; tokenizeElisp = elisp: tokenizeElisp' { inherit elisp; }; @@ -302,41 +304,43 @@ let # Convert literal value tokens in a flat list to their # corresponding nix representation. parseValues = tokens: - map (token: - if token.type == "string" then - token // { - value = substring 1 (stringLength token.value - 2) token.value; - } - else if token.type == "integer" then - token // { - value = fromJSON (removeStrings ["+" "."] token.value); - } - else if token.type == "symbol" && token.value == "t" then - token // { - value = true; - } - else if token.type == "float" then - let - initial = head (match "([+-]?([[:digit:]]*[.])?[[:digit:]]+(e([+-]?[[:digit:]]+|[+](INF|NaN)))?)" token.value); - isSpecial = (match "(.+(e[+](INF|NaN)))" initial) != null; - withoutPlus = removeStrings ["+"] initial; - withPrefix = - if substring 0 1 withoutPlus == "." then - "0" + withoutPlus - else if substring 0 2 withoutPlus == "-." then - "-0" + removeStrings ["-"] withoutPlus - else - withoutPlus; - in + map + (token: + if token.type == "string" then + token // { + value = substring 1 (stringLength token.value - 2) token.value; + } + else if token.type == "integer" then + token // { + value = fromJSON (removeStrings [ "+" "." ] token.value); + } + else if token.type == "symbol" && token.value == "t" then + token // { + value = true; + } + else if token.type == "float" then + let + initial = head (match "([+-]?([[:digit:]]*[.])?[[:digit:]]+(e([+-]?[[:digit:]]+|[+](INF|NaN)))?)" token.value); + isSpecial = (match "(.+(e[+](INF|NaN)))" initial) != null; + withoutPlus = removeStrings [ "+" ] initial; + withPrefix = + if substring 0 1 withoutPlus == "." then + "0" + withoutPlus + else if substring 0 2 withoutPlus == "-." then + "-0" + removeStrings [ "-" ] withoutPlus + else + withoutPlus; + in if !isSpecial && withPrefix != null then token // { value = fromJSON withPrefix; } else token - else - token - ) tokens; + else + token + ) + tokens; # Convert pairs of opening and closing tokens to their # respective collection types, i.e. lists and vectors. Also, @@ -363,52 +367,52 @@ let openColl = if token.type == "openParen" then "list" else if token.type == "openBracket" then "vector" else null; closeColl = if token.type == "closeParen" then "list" else if token.type == "closeBracket" then "vector" else null; in - if openColl != null then - state // { - acc = [ [] ] ++ seq (head state.acc) state.acc; - inColl = [ openColl ] ++ state.inColl; - depth = state.depth + 1; - line = [ token.line ] ++ state.line; - } - else if closeColl != null then - if (head state.inColl) == closeColl then - let - outerColl = elemAt state.acc 1; - currColl = { - type = closeColl; - value = head state.acc; - line = head state.line; - inherit (state) depth; - }; - rest = tail (tail state.acc); - in - state // seq state.acc { - acc = [ (outerColl ++ [ currColl ]) ] ++ rest; - inColl = tail state.inColl; - depth = state.depth - 1; - line = tail state.line; - } - else - throw "Unmatched ${token.type} on line ${toString token.line}" - else if token.type == "symbol" && token.value == "nil" then + if openColl != null then + state // { + acc = [ [ ] ] ++ seq (head state.acc) state.acc; + inColl = [ openColl ] ++ state.inColl; + depth = state.depth + 1; + line = [ token.line ] ++ state.line; + } + else if closeColl != null then + if (head state.inColl) == closeColl then let - currColl = head state.acc; - rest = tail state.acc; - emptyList = { - type = "list"; - depth = state.depth + 1; - value = []; + outerColl = elemAt state.acc 1; + currColl = { + type = closeColl; + value = head state.acc; + line = head state.line; + inherit (state) depth; }; + rest = tail (tail state.acc); in - state // seq currColl { acc = [ (currColl ++ [ emptyList ]) ] ++ rest; } + state // seq state.acc { + acc = [ (outerColl ++ [ currColl ]) ] ++ rest; + inColl = tail state.inColl; + depth = state.depth - 1; + line = tail state.line; + } else - let - currColl = head state.acc; - rest = tail state.acc; - in - state // seq currColl { acc = [ (currColl ++ [ token ]) ] ++ rest; }; + throw "Unmatched ${token.type} on line ${toString token.line}" + else if token.type == "symbol" && token.value == "nil" then + let + currColl = head state.acc; + rest = tail state.acc; + emptyList = { + type = "list"; + depth = state.depth + 1; + value = [ ]; + }; + in + state // seq currColl { acc = [ (currColl ++ [ emptyList ]) ] ++ rest; } + else + let + currColl = head state.acc; + rest = tail state.acc; + in + state // seq currColl { acc = [ (currColl ++ [ token ]) ] ++ rest; }; in - head (builtins.foldl' parseToken { acc = [ [] ]; inColl = [ null ]; depth = -1; line = []; } tokens).acc; + head (builtins.foldl' parseToken { acc = [ [ ] ]; inColl = [ null ]; depth = -1; line = [ ]; } tokens).acc; # Handle dotted pair notation, a syntax where the car and cdr # are represented explicitly. See @@ -434,33 +438,35 @@ let throw ''"Dotted pair notation"-dot outside list on line ${toString token.line}'' else if isList token.value then let - collectionContents = foldl' parseToken { - acc = []; - dotted = false; - inList = token.type == "list"; - inherit (state) depthReduction; - } token.value; + collectionContents = foldl' parseToken + { + acc = [ ]; + dotted = false; + inList = token.type == "list"; + inherit (state) depthReduction; + } + token.value; in - state // { - acc = state.acc ++ ( - if state.dotted then - collectionContents.acc - else - [ - (token // { - value = collectionContents.acc; - depth = token.depth - state.depthReduction; - }) - ] - ); - dotted = false; - } + state // { + acc = state.acc ++ ( + if state.dotted then + collectionContents.acc + else + [ + (token // { + value = collectionContents.acc; + depth = token.depth - state.depthReduction; + }) + ] + ); + dotted = false; + } else state // { - acc = state.acc ++ [token]; + acc = state.acc ++ [ token ]; }; in - (foldl' parseToken { acc = []; dotted = false; inList = false; depthReduction = 0; } tokens).acc; + (foldl' parseToken { acc = [ ]; dotted = false; inList = false; depthReduction = 0; } tokens).acc; parseQuotes = tokens: let @@ -469,35 +475,35 @@ let token = if isList token'.value then token' // { - value = (foldl' parseToken { acc = []; quotes = []; } token'.value).acc; + value = (foldl' parseToken { acc = [ ]; quotes = [ ]; } token'.value).acc; } else token'; in - if elem token.type [ "quote" "expand" "slice" "backquote" "function" "record" "byteCode" ] then - state // { - quotes = [ token ] ++ state.quotes; - } - else if state.quotes != [] then - let - quote = value: token: - token // { - inherit value; - }; - quotedValue = foldl' quote token state.quotes; - in - state // { - acc = state.acc ++ [ quotedValue ]; - quotes = []; - } - else - state // { - acc = state.acc ++ [ token ]; - }; + if elem token.type [ "quote" "expand" "slice" "backquote" "function" "record" "byteCode" ] then + state // { + quotes = [ token ] ++ state.quotes; + } + else if state.quotes != [ ] then + let + quote = value: token: + token // { + inherit value; + }; + quotedValue = foldl' quote token state.quotes; + in + state // { + acc = state.acc ++ [ quotedValue ]; + quotes = [ ]; + } + else + state // { + acc = state.acc ++ [ token ]; + }; in - (foldl' parseToken { acc = []; quotes = []; } tokens).acc; + (foldl' parseToken { acc = [ ]; quotes = [ ]; } tokens).acc; in - parseQuotes (parseDots (parseCollections (parseValues tokens))); + parseQuotes (parseDots (parseCollections (parseValues tokens))); parseElisp = elisp: parseElisp' (tokenizeElisp elisp); @@ -508,23 +514,23 @@ let if isList object.value then map readObject object.value else if object.type == "quote" then - ["quote" (readObject object.value)] + [ "quote" (readObject object.value) ] else if object.type == "backquote" then - ["`" (readObject object.value)] + [ "`" (readObject object.value) ] else if object.type == "expand" then - ["," (readObject object.value)] + [ "," (readObject object.value) ] else if object.type == "slice" then - [",@" (readObject object.value)] + [ ",@" (readObject object.value) ] else if object.type == "function" then - ["#'" (readObject object.value)] + [ "#'" (readObject object.value) ] else if object.type == "byteCode" then - ["#"] ++ (readObject object.value) + [ "#" ] ++ (readObject object.value) else if object.type == "record" then - ["#s"] ++ (readObject object.value) + [ "#s" ] ++ (readObject object.value) else object.value; in - map readObject ast; + map readObject ast; fromElisp = elisp: fromElisp' (parseElisp elisp); @@ -570,135 +576,137 @@ let force = expr: seq state.pos (seq state.line expr); in - if state.skip > 0 then - state // force { - pos = state.pos + 1; - skip = state.skip - 1; - line = if char == "\n" then state.line + 1 else state.line; - leadingWhitespace = char == "\n" || (state.leadingWhitespace && elem char [ " " "\t" "\r" ]); - } - else if char == "#" && state.leadingWhitespace && !state.readBody && beginCodeBlock != null then + if state.skip > 0 then + state // force { + pos = state.pos + 1; + skip = state.skip - 1; + line = if char == "\n" then state.line + 1 else state.line; + leadingWhitespace = char == "\n" || (state.leadingWhitespace && elem char [ " " "\t" "\r" ]); + } + else if char == "#" && state.leadingWhitespace && !state.readBody && beginCodeBlock != null then + state // { + pos = state.pos + 1; + skip = (stringLength beginCodeBlock) - 1; + leadingWhitespace = false; + readLanguage = true; + } + else if char == "#" && state.leadingWhitespace && !state.readBody && header != null then + state // { + pos = state.pos + 1; + skip = (stringLength header) - 1; + leadingWhitespace = false; + readFlags = true; + } + else if state.readLanguage then + if language != null then state // { + block = state.block // { + language = elemAt language 1; + }; pos = state.pos + 1; - skip = (stringLength beginCodeBlock) - 1; - leadingWhitespace = false; - readLanguage = true; - } - else if char == "#" && state.leadingWhitespace && !state.readBody && header != null then - state // { - pos = state.pos + 1; - skip = (stringLength header) - 1; + skip = (foldl' (total: string: total + (stringLength string)) 0 language) - 1; leadingWhitespace = false; + readLanguage = false; readFlags = true; + readBody = true; } - else if state.readLanguage then - if language != null then - state // { - block = state.block // { - language = elemAt language 1; - }; - pos = state.pos + 1; - skip = (foldl' (total: string: total + (stringLength string)) 0 language) - 1; - leadingWhitespace = false; - readLanguage = false; - readFlags = true; - readBody = true; - } - else throw "Language missing or invalid for code block on line ${toString state.line}!" - else if state.readFlags then - if flags != null then - let - parseFlag = state: item: - let - prefix = if isString item then substring 0 1 item else null; - in - if elem prefix [ ":" "-" "+" ] then - state // { - acc = state.acc // { ${item} = true; }; - flag = item; - } - else if state.flag != null then - state // { - acc = state.acc // { ${state.flag} = item; }; - flag = null; - } - else - state; - in - state // { - block = state.block // { - flags = - (foldl' - parseFlag - { acc = state.block.flags; - flag = null; - inherit (state) line; - } - (fromElisp flags)).acc; - startLineNumber = state.line + 1; - }; - pos = state.pos + 1; - skip = (stringLength flags) - 1; - line = if char == "\n" then state.line + 1 else state.line; - leadingWhitespace = char == "\n"; - readFlags = false; - } - else throw "Arguments malformed for code block on line ${toString state.line}!" - else if char == "#" && state.leadingWhitespace && endCodeBlock != null then + else throw "Language missing or invalid for code block on line ${toString state.line}!" + else if state.readFlags then + if flags != null then + let + parseFlag = state: item: + let + prefix = if isString item then substring 0 1 item else null; + in + if elem prefix [ ":" "-" "+" ] then + state // { + acc = state.acc // { ${item} = true; }; + flag = item; + } + else if state.flag != null then + state // { + acc = state.acc // { ${state.flag} = item; }; + flag = null; + } + else + state; + in state // { - acc = state.acc ++ [ state.block ]; - block = { - language = null; - body = ""; - flags = {}; + block = state.block // { + flags = + (foldl' + parseFlag + { + acc = state.block.flags; + flag = null; + inherit (state) line; + } + (fromElisp flags)).acc; + startLineNumber = state.line + 1; }; pos = state.pos + 1; - skip = (stringLength endCodeBlock) - 1; - leadingWhitespace = false; - readBody = false; + skip = (stringLength flags) - 1; + line = if char == "\n" then state.line + 1 else state.line; + leadingWhitespace = char == "\n"; + readFlags = false; } - else if state.readBody then - let - mod = state.pos / 100; - newState = { - block = state.block // { - body = state.block.body + char; - }; - inherit mod; - pos = state.pos + 1; - line = if char == "\n" then state.line + 1 else state.line; - leadingWhitespace = char == "\n" || (state.leadingWhitespace && elem char [ " " "\t" "\r" ]); + else throw "Arguments malformed for code block on line ${toString state.line}!" + else if char == "#" && state.leadingWhitespace && endCodeBlock != null then + state // { + acc = state.acc ++ [ state.block ]; + block = { + language = null; + body = ""; + flags = { }; + }; + pos = state.pos + 1; + skip = (stringLength endCodeBlock) - 1; + leadingWhitespace = false; + readBody = false; + } + else if state.readBody then + let + mod = state.pos / 100; + newState = { + block = state.block // { + body = state.block.body + char; }; - in - if mod > state.mod then - state // seq state.block.body (force newState) - else - state // newState - else - state // force { + inherit mod; pos = state.pos + 1; line = if char == "\n" then state.line + 1 else state.line; leadingWhitespace = char == "\n" || (state.leadingWhitespace && elem char [ " " "\t" "\r" ]); }; - in - (foldl' - parseToken - { acc = []; - mod = 0; - pos = 0; - skip = 0; - line = 1; - block = { - language = null; - body = ""; - flags = {}; + in + if mod > state.mod then + state // seq state.block.body (force newState) + else + state // newState + else + state // force { + pos = state.pos + 1; + line = if char == "\n" then state.line + 1 else state.line; + leadingWhitespace = char == "\n" || (state.leadingWhitespace && elem char [ " " "\t" "\r" ]); }; - leadingWhitespace = true; - readLanguage = false; - readFlags = false; - readBody = false; - } - (stringToCharacters text)).acc; + in + (foldl' + parseToken + { + acc = [ ]; + mod = 0; + pos = 0; + skip = 0; + line = 1; + block = { + language = null; + body = ""; + flags = { }; + }; + leadingWhitespace = true; + readLanguage = false; + readFlags = false; + readBody = false; + } + (stringToCharacters text)).acc; # Run tokenizeElisp' on all Elisp code blocks (with `:tangle yes` # set) from an Org mode babel text. If the block doesn't have a @@ -712,19 +720,19 @@ let tangle = toLower (block.flags.":tangle" or defaultArgs.":tangle" or "no"); language = toLower block.language; in - elem language [ "elisp" "emacs-lisp" ] - && elem tangle [ "yes" ''"yes"'' ]) + elem language [ "elisp" "emacs-lisp" ] + && elem tangle [ "yes" ''"yes"'' ]) (parseOrgModeBabel text); - in - foldl' - (result: codeBlock: - result ++ (tokenizeElisp' { - elisp = codeBlock.body; - inherit (codeBlock) startLineNumber; - }) - ) - [] - codeBlocks; + in + foldl' + (result: codeBlock: + result ++ (tokenizeElisp' { + elisp = codeBlock.body; + inherit (codeBlock) startLineNumber; + }) + ) + [ ] + codeBlocks; tokenizeOrgModeBabelElisp = tokenizeOrgModeBabelElisp' { diff --git a/nix/factory.nix b/nix/factory.nix index 34ddef5..d72e13f 100644 --- a/nix/factory.nix +++ b/nix/factory.nix @@ -13,10 +13,15 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . -{ lib, stdenv, emacs29, callPackage, writeShellApplication, noether -, emacsParams ? {}, - fg42Params ? {} -} : +{ lib +, stdenv +, emacs29 +, callPackage +, writeShellApplication +, noether +, emacsParams ? { } +, fg42Params ? { } +}: let lemacs = emacs29.override ({ withTreeSitter = true; @@ -44,7 +49,8 @@ let runtimeInputs = [ fg42 ]; text = '' - DISPLAY=:1 ${fg42}/bin/fg42-wm + DISPLAY=:1 ${fg42}/bin/fg42-wm ''; }; -in { inherit fg42 run-test-wm; } +in +{ inherit fg42 run-test-wm; } diff --git a/nix/fg42.nix b/nix/fg42.nix index f70179d..97c126d 100644 --- a/nix/fg42.nix +++ b/nix/fg42.nix @@ -13,21 +13,49 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . -{ lib, stdenv, elispPkgs, srcDir, emacsPackagesFor, ourPackages, direnv -, makeFontsConf, nix, nixpkgs-fmt -, nil, # nix lsp server +{ lib +, stdenv +, elispPkgs +, srcDir +, emacsPackagesFor +, ourPackages +, direnv +, makeFontsConf +, nix +, nixpkgs-fmt +, nil +, # nix lsp server # python deps - python311, python3Packages, - # This is a set of system tools required for FG42 + python311 +, python3Packages +, # This is a set of system tools required for FG42 # to work. - pyright, emacs, ripgrep, git, texinfo, vazir-fonts, fira-code, nerdfonts -, fira-mono, noto-fonts, gcc, ltex-ls, bash, tree-sitter, fd -, aspellWithDicts, - - supportWM ? true, xorg, slock, - - supportPython ? true, supportVerilog ? true, svls, verilator, }: + pyright +, emacs +, ripgrep +, git +, texinfo +, vazir-fonts +, fira-code +, nerdfonts +, fira-mono +, noto-fonts +, gcc +, ltex-ls +, bash +, tree-sitter +, fd +, aspellWithDicts +, supportWM ? true +, xorg +, slock +, supportPython ? true +, supportVerilog ? true +, svls +, verilator +, +}: with builtins; let version = "4.0.0"; @@ -43,7 +71,15 @@ let dicts = aspellWithDicts (dicts: with dicts; [ en en-computers en-science ]); runtimeBins = [ - ripgrep git tree-sitter direnv nix nil dicts fd nixpkgs-fmt + ripgrep + git + tree-sitter + direnv + nix + nil + dicts + fd + nixpkgs-fmt ] ++ (lib.optional (!stdenv.buildPlatform.isRiscV) [ # Not supported on Risc-V @@ -83,7 +119,8 @@ let ]; }; -in stdenv.mkDerivation (final: rec { +in +stdenv.mkDerivation (final: rec { inherit version; pname = "fg42"; src = srcDir; diff --git a/nix/maintainers.nix b/nix/maintainers.nix index 35f0561..28f8ced 100644 --- a/nix/maintainers.nix +++ b/nix/maintainers.nix @@ -18,7 +18,7 @@ lxsameer = { email = "lxsameer@lxsameer.com"; github = "lxsameer"; - git = "lxsameer"; + git = "lxsameer"; matrix = "@lxsameer:matrix.org"; name = "Sameer Rahmani"; keys = [{ diff --git a/nix/parse.nix b/nix/parse.nix index 0edb263..30db3ff 100644 --- a/nix/parse.nix +++ b/nix/parse.nix @@ -22,76 +22,77 @@ let (x: builtins.typeOf x == "string") (builtins.split _sep _s); -in { - elispStr +in +{ elispStr , alwaysEnsure ? false }: - let - inherit (import ./elisp_reader.nix { inherit lib; }) fromElisp; +let + inherit (import ./elisp_reader.nix { inherit lib; }) fromElisp; - readFunction = fromElisp; - find = item: list: - if list == [] then [] else - if builtins.head list == item then - list - else - find item (builtins.tail list); + readFunction = fromElisp; + find = item: list: + if list == [ ] then [ ] else + if builtins.head list == item then + list + else + find item (builtins.tail list); - getKeywordValue = keyword: list: + getKeywordValue = keyword: list: + let + keywordList = find keyword list; + in + if keywordList != [ ] then let - keywordList = find keyword list; + keywordValue = builtins.tail keywordList; in - if keywordList != [] then - let - keywordValue = builtins.tail keywordList; - in - if keywordValue != [] then - builtins.head keywordValue - else - true - else - null; - - isDisabled = item: - let - disabledValue = getKeywordValue ":disabled" item; - in - if disabledValue == [] then - false - else if builtins.isBool disabledValue then - disabledValue - else if builtins.isString disabledValue then - true - else - false; - - getName = item: - let - ensureValue = getKeywordValue ":ensure" item; - usePackageName = builtins.head (builtins.tail item); - in - if builtins.isString ensureValue then - if lib.hasPrefix ":" ensureValue then - usePackageName - else - ensureValue - else if ensureValue == true || (ensureValue == null && alwaysEnsure) then - usePackageName - else - []; - - recurse = item: - if builtins.isList item && item != [] then - let - packageManager = builtins.head item; - in - if builtins.elem packageManager [ "depends-on" ] then - if !(isDisabled item) then - [ packageManager (getName item) ] ++ map recurse item - else - [] - else - map recurse item + if keywordValue != [ ] then + builtins.head keywordValue else - []; - in lib.flatten (map recurse (readFunction elispStr)) + true + else + null; + + isDisabled = item: + let + disabledValue = getKeywordValue ":disabled" item; + in + if disabledValue == [ ] then + false + else if builtins.isBool disabledValue then + disabledValue + else if builtins.isString disabledValue then + true + else + false; + + getName = item: + let + ensureValue = getKeywordValue ":ensure" item; + usePackageName = builtins.head (builtins.tail item); + in + if builtins.isString ensureValue then + if lib.hasPrefix ":" ensureValue then + usePackageName + else + ensureValue + else if ensureValue == true || (ensureValue == null && alwaysEnsure) then + usePackageName + else + [ ]; + + recurse = item: + if builtins.isList item && item != [ ] then + let + packageManager = builtins.head item; + in + if builtins.elem packageManager [ "depends-on" ] then + if !(isDisabled item) then + [ packageManager (getName item) ] ++ map recurse item + else + [ ] + else + map recurse item + else + [ ]; +in +lib.flatten (map recurse (readFunction elispStr))