Code Monkey home page Code Monkey logo

nix-gui's Introduction

Nix-Gui

Make NixOS usable for non-technical users through a settings / package management GUI.

(Work in progress: more features and refinement necessary to meet the above goal)

screenshots/historical_2021_10_06.png

screenshots/historical_search_2021_10_10.png

Using

Prerequisites:

  • Ensure NixOS is installed

Run

  • nix run github:nix-gui/nix-gui

Print help string

  • nix run github:nix-gui/nix-gui -- --help

If you don’t have Nix Flakes enabled, either

  • Run nix --experimental-features 'nix-command flakes' run github:nix-gui/nix-gui, or
  • Set nix.extraOptions = ''experimental-features = nix-command flakes''; in configuration.nix and rebuild to enable.

For details on how to use Nix-Gui, see the Usage page.

Motives

The declarative nature of NixOS provides it the capability of being the most user friendly GNU/Linux distribution. No more editing dotfiles, /etc files, manually writing timers, services, running commands to manage and create users and groups, etc. NixOS integrates all of that into a declarative system, and this project integrates NixOS’ declarative system into a GUI.

Serve Users Unfamiliar with or Learning Nix

Nix-Gui is a configuration management tool designed for those who haven’t mastered the (arguably difficult) nix language. It is also an attempt to replicate the ease of use of popular configuration systems including

Nix-Gui is designed to gradually and comfortably teach users about the mechanics of the nix language and nixpkgs.

Serve as an Effective System Management Tool for Experienced Users

At the most advanced level, and once feature parity has been achieved. Power users should be capable of changing system configuration, creating system ISOs, deploying systems to the cloud, etc in Nix-Gui more intelligibly and faster than through their traditional means of writing a nix module.

Serve Mobile Users

An additional motive for this project is to enable system configuration for mobile devices without having to type code on your phone.

Functionality

Nix-Gui is a tool which loads data including option paths, option types, default values, configured values, descriptions, etc. The option hierarchy is made explorable and the value of individual options are editable. Changes are committed by writing to modules within the configuration path.

This data is retrieved from <nixos/nixpkgs> and from the configuration path via NIX_PATH nixos-configuration.

Features

  • View and edit the state of options using type-specific widgets (e.g. textbox for strings)
    • View and edit the actual nix expression defining an option
    • View metadata of an option including type and definition
  • Save changes to a relevant module in the configuration path
    • “Diff” to show option changes not yet committed to disk
  • Explore the hierarchy of options
    • Utilize color indicators of which options have been set
  • Search options based on options path, type, and description
  • Undo changes to options

Major Shortcomings to be Fixed

Currently there are a few major limitations to Nix-Gui, including

  • Documentation is can be improved.
  • Nix-Gui has yet to be thoroughly vetted, therefore the configuration path is copied to ~/.config/nixgui/configurations/, in which all changes made by Nix-Gui are saved.
  • Some option types aren’t handled yet (e.g. package, lambda, and specific types like ncdns.conf configuration type, systemd option). These options can only be edited as a nix expression, as they do not have a matching widget.

Documentation

Contributing

Developers and users, if you want to help please

  • Run the application and submit bug report and feature request issues on GitHub.
  • Contribute to the UX Survey.
  • Read the Development documentation in the section above.
  • Review existing pull requests.
  • See good first issues.
  • Create issues to ask questions about code, documentation, etc (there are no dumb questions).
  • Contribute to important dependencies including rnix-parser and rnix-lsp.
  • Join the matrix below to discuss.

Matrix

Development, support, discussion on Matrix #nix-gui:nixos.org https://matrix.to/#/#nix-gui:nixos.org

nix-gui's People

Contributors

adrianparvino avatar boredom101 avatar jeffa5 avatar jgarte avatar lapp0 avatar lillecarl avatar milahu avatar tusharsadhwani avatar yater avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

nix-gui's Issues

Implement basic logging

  • add debug / error log lines to appropriate functions
  • handle stdout and stderr in subprocess

Unit Testing

  • sample configuration files
  • run api against sample
  • include in setup.py and flake.nix

Discuss: User Friendliness Initiative

Please share your thoughts on different ways we might make nix-gui have the lowest technical barrier possible.

Here are my thoughts on different improvements we could make:

  • Great search functionality
  • Readable and Comprehensive Documentation
  • Hold the users hand while configuring
  • Link to official nix / package documentation for specific options
  • Allow users to add unofficial modules that make configuration easier**

When using import in configuration.nix the script searches in its working directory

My configuration.nix contains a the following line:

    shellAliases = import ./modules/aliases.nix;

which leads to the following error because nix-gui is searching in its own relative path:

INFO:error: getting status of '/home/vincenzo/Code/nix-gui/modules/aliases.nix': No such file or directory

The program launches regardless of the error though.

Improve indentation, spacing, and location of placement in code injection

Current

Attribute replacement: problems to fix

  • too many newlines were added,
  • the indentation was removed
  • the semicolon has a newline before it

Before:

  programs = {
    zsh.enable = true;
    vim.enable = true;  # don't actually use vim, this is just an example file
  };

After changing zsh.enable to False

  programs = {
    

# Attribute defined by Nix-Gui
zsh.enable = false
;
    vim.enable = true;  # don't actually use vim, this is just an example file
  };

Attribute Addition: problems to fix

  • not placed within attribute set specific to "parent" attribute
  • not placed after imports
  • indentation broken
  • newline before semicolon

fonts.fontconfig.hinting.autohint was placed as such:

let
  vars = import ./vars.nix {};
in {

# Attribute defined by Nix-Gui
fonts.fontconfig.hinting.autohint = true
;
  imports = [
    ./hardware-configuration.nix
  ];

Despite thefonts attr set being defined elsewhere

  fonts = {
    fontDir.enable = true;
    fonts = with pkgs; [
      go-font
      sudo-font
    ];
  };

Additionally, lookup for the location of option definitions is incorrect for the "canonical form"

UTF-8 supports

Hello,

I tryied again, it failed again =P

It seems that it does not like a character in a comment
https://gitlab.com/pinage404/dotfiles/-/blob/d1be7b97e47fececa56927446fab0644fabfb563/nixos/machine/gigabyte_sabre_15/configuration.nix#L2

CONFIGURATION_PATH=/etc/nixos/configuration.nix nixFlakes run github:lapp0/nix-gui
warning: ignoring the user-specified setting 'experimental-features', because it is a restricted setting and you are not a trusted user
Traceback (most recent call last):
  File "/nix/store/agjny99n2ny4pc5zn46pima7rabb2ysq-python3.8-parsimonious-0.8.1/lib/python3.8/site-packages/parsimonious/nodes.py", line 217, in visit
    return method(node, [self.visit(n) for n in node])
  File "/nix/store/fdazal8y5az6vg0z5r8d6wb82ys4j5pi-python3.8-nix-gui-0.1.0/lib/python3.8/site-packages/nixui/parser/ast.py", line 105, in visit_token
    quoted = quoted.encode('utf-8').decode('unicode_escape')  # unescape
UnicodeDecodeError: 'unicodeescape' codec can't decode bytes in position 104-105: truncated \uXXXX escape

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/nix/store/fdazal8y5az6vg0z5r8d6wb82ys4j5pi-python3.8-nix-gui-0.1.0/bin/.nix-gui-wrapped", line 9, in <module>
    sys.exit(main())
  File "/nix/store/fdazal8y5az6vg0z5r8d6wb82ys4j5pi-python3.8-nix-gui-0.1.0/lib/python3.8/site-packages/nixui/gui.py", line 66, in main
    statemodel = state_model.StateModel()
  File "/nix/store/fdazal8y5az6vg0z5r8d6wb82ys4j5pi-python3.8-nix-gui-0.1.0/lib/python3.8/site-packages/nixui/state_model.py", line 12, in __init__
    self.current_values = api.get_option_values_map()
  File "/nix/store/fdazal8y5az6vg0z5r8d6wb82ys4j5pi-python3.8-nix-gui-0.1.0/lib/python3.8/site-packages/nixui/api.py", line 65, in get_option_values_map
    for option, option_data in get_option_data().items()
  File "/nix/store/fdazal8y5az6vg0z5r8d6wb82ys4j5pi-python3.8-nix-gui-0.1.0/lib/python3.8/site-packages/nixui/api.py", line 39, in get_option_data
    configured_values = {'.'.join(k): v for k, v in parser.get_all_option_values(os.environ['CONFIGURATION_PATH']).items()}
  File "/nix/store/fdazal8y5az6vg0z5r8d6wb82ys4j5pi-python3.8-nix-gui-0.1.0/lib/python3.8/site-packages/nixui/parser/parser.py", line 11, in get_all_option_values
    syntax_tree = ast.get_ast(module_path)
  File "/nix/store/fdazal8y5az6vg0z5r8d6wb82ys4j5pi-python3.8-nix-gui-0.1.0/lib/python3.8/site-packages/nixui/parser/ast.py", line 38, in get_ast
    return parse_ast_str(ast_str)
  File "/nix/store/fdazal8y5az6vg0z5r8d6wb82ys4j5pi-python3.8-nix-gui-0.1.0/lib/python3.8/site-packages/nixui/parser/ast.py", line 55, in parse_ast_str
    root_node = NixVisitor().visit(tree)
  File "/nix/store/agjny99n2ny4pc5zn46pima7rabb2ysq-python3.8-parsimonious-0.8.1/lib/python3.8/site-packages/parsimonious/nodes.py", line 217, in visit
    return method(node, [self.visit(n) for n in node])
  File "/nix/store/agjny99n2ny4pc5zn46pima7rabb2ysq-python3.8-parsimonious-0.8.1/lib/python3.8/site-packages/parsimonious/nodes.py", line 217, in <listcomp>
    return method(node, [self.visit(n) for n in node])
  File "/nix/store/agjny99n2ny4pc5zn46pima7rabb2ysq-python3.8-parsimonious-0.8.1/lib/python3.8/site-packages/parsimonious/nodes.py", line 217, in visit
    return method(node, [self.visit(n) for n in node])
  File "/nix/store/agjny99n2ny4pc5zn46pima7rabb2ysq-python3.8-parsimonious-0.8.1/lib/python3.8/site-packages/parsimonious/nodes.py", line 217, in <listcomp>
    return method(node, [self.visit(n) for n in node])
  File "/nix/store/agjny99n2ny4pc5zn46pima7rabb2ysq-python3.8-parsimonious-0.8.1/lib/python3.8/site-packages/parsimonious/nodes.py", line 217, in visit
    return method(node, [self.visit(n) for n in node])
  File "/nix/store/agjny99n2ny4pc5zn46pima7rabb2ysq-python3.8-parsimonious-0.8.1/lib/python3.8/site-packages/parsimonious/nodes.py", line 217, in <listcomp>
    return method(node, [self.visit(n) for n in node])
  File "/nix/store/agjny99n2ny4pc5zn46pima7rabb2ysq-python3.8-parsimonious-0.8.1/lib/python3.8/site-packages/parsimonious/nodes.py", line 217, in visit
    return method(node, [self.visit(n) for n in node])
  File "/nix/store/agjny99n2ny4pc5zn46pima7rabb2ysq-python3.8-parsimonious-0.8.1/lib/python3.8/site-packages/parsimonious/nodes.py", line 217, in <listcomp>
    return method(node, [self.visit(n) for n in node])
  File "/nix/store/agjny99n2ny4pc5zn46pima7rabb2ysq-python3.8-parsimonious-0.8.1/lib/python3.8/site-packages/parsimonious/nodes.py", line 217, in visit
    return method(node, [self.visit(n) for n in node])
  File "/nix/store/agjny99n2ny4pc5zn46pima7rabb2ysq-python3.8-parsimonious-0.8.1/lib/python3.8/site-packages/parsimonious/nodes.py", line 217, in <listcomp>
    return method(node, [self.visit(n) for n in node])
  File "/nix/store/agjny99n2ny4pc5zn46pima7rabb2ysq-python3.8-parsimonious-0.8.1/lib/python3.8/site-packages/parsimonious/nodes.py", line 227, in visit
    reraise(VisitationError, VisitationError(exc, exc_class, node), tb)
  File "/nix/store/14sil57w425v7ncx8jk9rwb1zz7ix204-python3.8-six-1.15.0/lib/python3.8/site-packages/six.py", line 702, in reraise
    raise value.with_traceback(tb)
  File "/nix/store/agjny99n2ny4pc5zn46pima7rabb2ysq-python3.8-parsimonious-0.8.1/lib/python3.8/site-packages/parsimonious/nodes.py", line 217, in visit
    return method(node, [self.visit(n) for n in node])
  File "/nix/store/fdazal8y5az6vg0z5r8d6wb82ys4j5pi-python3.8-nix-gui-0.1.0/lib/python3.8/site-packages/nixui/parser/ast.py", line 105, in visit_token
    quoted = quoted.encode('utf-8').decode('unicode_escape')  # unescape
parsimonious.exceptions.VisitationError: UnicodeDecodeError: 'unicodeescape' codec can't decode bytes in position 104-105: truncated \uXXXX escape

Parse tree:
<Node called "token" matching "TOKEN_COMMENT("# Help is available in the configuration.nix(5) man page and in the NixOS manual (accessible by running \u{2018}nixos-help\u{2019})") 81..202
  ">  <-- *** We were here. ***
    <RegexNode called "name" matching "TOKEN_COMMENT">
    <Node called "lpar" matching "(">
    <RegexNode called "quoted" matching ""# Help is available in the configuration.nix(5) man page and in the NixOS manual (accessible by running \u{2018}nixos-help\u{2019})"">
    <Node called "rpar" matching ")">
    <RegexNode called "ws" matching " ">
    <RegexNode called "numrange" matching "81..202">
    <RegexNode called "ws" matching "
      ">

License

I'm interested in contributing to this or a similar project, but license affects my decision. Can you add a license? Preferably MIT because nixpkgs uses it.

Improvements to Diff Viewer

Current State

The diff viewer is a simple no frills widget that shows each options changes using pythons difflib in a single QPlainTextEdit

Desired State

  • We should have an advanced, visually appealing diff viewer similar to https://github.com/yebrahim/pydiff
  • Show full option paths on left (currently only shows the last part of the option path)
  • state which module the changes will be saved to

File New

  • File menu
    • Edit configuration.nix
    • New Configuration
      • ISO
      • NixOps
      • Flake

QT Window not opening when running with basic config

Calling CONFIGURATION_PATH=/etc/nixos/configuration.nix nix run github:lapp0/nix-gui with minimal config leads to a qt window being opened for the fraction of a second and then aborting with an error. Qtile is installed with home manager and works with other applications.

Config I tried to use:

{ config, pkgs, ... }:

{
  imports =
    [
      ./hardware-configuration.nix
    ];

  boot.loader.systemd-boot.enable = true;
  boot.loader.efi.canTouchEfiVariables = true;
  nixpkgs.config.allowUnfree = true;

  networking.hostName = "nixos"; # Define your hostname.

  time.timeZone = "Europe/Berlin";

  networking.useDHCP = false;
  networking.interfaces.enp0s31f6.useDHCP = true;

  i18n.defaultLocale = "en_US.UTF-8";
  console = {
    font = "Lat2-Terminus16";
    keyMap = "us";
  };

  services.xserver.enable = true;
  services.xserver.displayManager.sddm.enable = true;
  services.xserver.desktopManager.plasma5.enable = true;


  services.xserver.layout = "us";
  services.xserver.xkbOptions = "eurosign:e";

  services.printing.enable = true;

  sound.enable = true;
  hardware.pulseaudio.enable = true;


  users.users.vincenzo = {
    isNormalUser = true;
    initialPassword = "password";
    extraGroups = [ "wheel" ];
  };

  services.openssh.enable = true;
  system.autoUpgrade = {
	enable = true;
  };
  system.stateVersion = "20.09";

  nix = {
	trustedUsers = [ "root" "vincenzo" ];
  };
}

Error message I received:

Traceback (most recent call last):
  File "/nix/store/fdazal8y5az6vg0z5r8d6wb82ys4j5pi-python3.8-nix-gui-0.1.0/lib/python3.8/site-packages/nixui/richtext.py", line 15, in paint
    textRect = style.subElementRect(QtWidgets.QStyle.SE_ItemViewItemText, option)
TypeError: subElementRect(self, QStyle.SubElement, QStyleOption, QWidget): not enough arguments
Aborted (core dumped)

FloatField

Floats are very rare (less than 20 options with float as a possible type). It's easy to implement the simple form of it though.

Similar structure to other widgets in field_widgets.py.

Read imports from CONFIGURATION_PATH

Current

CONFIGURATION_PATH is the only module checked for user-defined options

Desired

CONFIGURATION_PATH's imports are used to recursively collect modules from which user-defined options will be determined

"Common Patterns" of Options

Use "common options" datastructure from #21 to create a dialog which allows users to

  • select a "pattern" from a list of available patters (e.g. "configure a user", or "configure an SSH server")
  • show a list of options to set, e.g. users.extraUsers.<name>' + (isNormalUser, home, description, extraGroups, shell`)

"Recommended" Options

  • parse nix configurations in github and get sets of options defined together
  • create collaborative filtering data cache in repo
  • use cache to determine a list of options which are commonly associated with the options the user has set (either in memory, or in configuration.nix)
  • create new "Recommended Options" QAction that queries this datastructure

Consistent Naming

Python disallows dashes in module names. nixui and nix-gui will both be renamed to nixgui

Exit QAction

ctl+q, file>exit both should result in the program exiting.

Search All Attributes QAction

  • search QDialog including
    • search box
    • [ ] list widget which dynamically filters results based on contents of search box (using option name, description, type, value)
      • no longer doing, search is a 1 second operation, dynamic filtering per character change would be too expensive (for now)
    • double clicking a list widget item results in navigating the option tree and selecting the options field widget
  • Toolbar "Search" and "ctrl+f" both bring forth this QDialog

Use similar search algorithm as in this project http://rew.la/coursesearch/#genetics

Support flakes

Support flakes form of configuration.nix

nix run nix-gui --flake <uri>

Integrate Language Server

Current state:

  • We can only get the set values of options via nixos-option and the default values via nix-build /etc/nixos/nixpkgs/nixos/release.nix -A options -o release_out
  • We can only get the set of packages via nix-env -qaP --out-path -f '<nixpkgs>' > all_packages_out
  • We cannot get the value of an attribute without evaluating (we cannot edit the actual source of an attribute, this disallows things like string substitution, referencing packages, referencing submodules, and writing expressions)

Motive:
Integrating rnix-lsp combined with unsafeGetAttrPos will provide the ability to retrieve the unevaluated values of options and other expressions.

Implementation:
Integration will utilize pylspclient as the client interface to rnix-lsp. Combined with unsafeGetAttrPos, this will allow the reading of the raw value of options, the evaluation of legal options for with statements, contextualizing legal identifiers based on imports, among other things.

This interface will be queried by api.py to

  • retrieve unevaluated value of an option set
  • implement the package manager for list of packages and package type options
  • provide a myriad of other useful functionality to the program further down the road

Blocker:

  • rnix-eval-lsp functionality must be merged into rnix-lsp nix-community/rnix-lsp#38
  • afterwards rnix-lsp must have additional functionality such as evaluating paths such as <nixpkgs> and "goto definition" among other things.

Restructure Python Modules

Change Directory Structure

Currently nixui/ is flat and a mixed bag of modules. It should be split into

  • nixui/graphics/: All widgets, windows, and other graphical components.

  • nixui/options/: parser.py, nix_eval.py, and ast.py to extract <nixpkgs> state, api.py - an encapsulated interface to retrieve and write option data using parser.py, nix_eval.py, and ast.py

  • nixui/utils/: Logging, generic datastructures, generic decorators, store.py, and any other components that aren't specific to graphics or option getting/setting.

  • nixui/state_model.py manages signals and slots to handle interactions between graphical components, manages in-memory option state, and acts as an interface between graphical components and nixui.options. It is only imported by nixui/main.py, but is passed as an argument to most graphical components.

  • nixui/main.py: put the pieces together and launch the program

Split Nix Expressions into Separate Template Files

#24 (comment)

Trace Side Effects of Option

We should let the user be aware of the side effects of setting an option based on the config definition.

e.g. services.hardware.tlp.enable = true; impacts

  • boot.kernelModules
  • environment.etc."tlp.conf".text
  • environment.systemPackages
  • services.tlp.settings
  • services.udev.packages
  • systemd

Get all option values via `rnix-parser`

Currently

Default values are retrieved via

        subprocess.run([
            'nix-build',
            '/etc/nixos/nixpkgs/nixos/release.nix',
            '-A',
            'options',
            '-o',
            release_path
        ])

User set values are retrieved from CONFIGURATION_PATH via unsafeGetAttrPos and an interface to rnix-parser

Desired

(Edited)

  • Parse and retrieve the unevaluated expression for each <nixpkgs/nixos> option
  • parse much quicker than release.nix can be built

Proposed Implementation (retracted)

  • parseoptions.rs (based on rnix-parser) is used to parse all of nixpkgs and CONFIGURATION_PATH
  • parseoptions.rs spits out module, option, value_expression
  • api.py calls parseoptions.rs and retrieves all option values

New Proposed Implementation

  • Prior to launching the application, if <nixpkgs/nixos> has changed since last run, cache the module, line, and column of each option with an expression utilizing unsafeGetAttrPos
  • At runtime dump and cache the modules AST for the option being looked up, lookup line and column of the AST, and extract the options unevaluated expression (similar to how parser.py currently extracts the source of options inCONFIGURATION_PATH https://github.com/lapp0/nix-gui/blob/master/nixui/parser/parser.py#L7-L25)

Load Icons

Currently cloning the repo and running nix run allows icons to be load, but nix run github:lapp0/nix-gui doesn't work.

Icons are referenced via pkgutil in icon.py, and are bundled in setup.py. Not sure what's going wrong here yet.

Parse Escape Quotes in ast.py

Lines of ast.py that should be replaced:

ast_str = ast_str.decode().replace('\\\"', 'EQ') # TODO 3929: fix hack - can't parse \" properly

quoted = quoted.replace('EQ', '\"') # TODO: fix hack (see note 3929 above)

quoted = quoted.encode('utf-8').decode('unicode_escape') # unescape

This is failing because the regexp isn't working:
quoted = ~r'"[^\"]+"'

Misc Build Improvements

Right now there are a few problems in the build and development cycle.

  • even after nix run has completed the build process and has run once, running nix run again is relatively slow, taking 1.78 seconds and showing [0/1 built]. Why does it need to rebuild?
  • We need documentation on how to run pdb while developing in using.org
  • We need documentation on how to run tests without running the code in using.org
  • We need documentation on how to run tests with profiling
  • We need documentation on how to run tests with a coverage report
  • We need to be able to make changes to python code without having to rebuild every time. This /may/ be doable via python3 setup.py develop
  • ability to run specific tests
    • I tried this in nix develop, but python3 -m pytest nixui/tests/test_option_tree.py fails because the dev shell doesn't have nix-gui/tests/sample.
    • We currently have this semi-working through #213 , but passing parameters to flakes is currently disallowed https://discourse.nixos.org/t/passing-options-to-flakes/7579/3 so the full implementation isn't workable yet
    • look into running specific tests in development environment

Use NIX_PATH rather than assuming an hard coded location

Hi,

first of thanks for your great work having a soild UI would make NixOS a lot more accessible. However I still had some difficulties to get the program since it assumes an nixpkgs checkout in /etc/nixos/nixpkgswhich I didn't have.

I got around the issue by generating options.json using NIX_PATH
nix-build '<nixpkgs/nixos/release.nix>' -A options -o $HOME/.config/nixgui/release_out

I also couldn't load my system settings since I use flakes but I'm guessing that'd be an feature for the next major version.

Clean up ScrollListStackSelector and inheriting classes

Some functionality of ScrollListStackSelector is implemented redundantly in subclasses.

There will always need to be a handler that maps list item to stack item.

change_item should internally handle changing adding the stack item, changing to that stack item, and removing the old one.

There should be a default method to handle adding items

Inheriting classes need to be fixed to reflect these changes.

Color OptionListWidget based on the state of child options

If a foo.bar.baz is active, the OptionListWidget for foo.bar and foo should be <active color>

else if foo.bar.baz is invalid, the same should be true for <invalid color>

else if foo.bar.baz is edited in memory, the same should be true for <edited color>

else if foo.bar.baz is edited from its default and committed to disc, it should be <change committed color>

else it should be the default color

Implement load_value for AttributeSetOf

Currently AttributeSetOf in widgets.py doesn't actually load values from api, it just does nothing. Other field types such as OptionGroupBox can be used as an example for what load_value must accomplish.

Make Option Data API Sane

Current

api.py bundles together each options type, description, default, user set value, and the expression for the user set value.

Desired

Separate the data defined in <nixos/nixpkgs> and CONFIGURATION_PATH

  • Schema (overloading the term): return a mapping of option ID -> Schema(type, description, default_expr, num_children)
  • Value: return a mapping of option ID -> user_defined_expr

How to run it ?

Hi

I just tried to run it, but it didn't work

nixFlakes run github:lapp0/nix-gui
warning: ignoring the user-specified setting 'experimental-features', because it is a restricted setting and you are not a trusted user
Traceback (most recent call last):
  File "/nix/store/q3yrkldj3jh44z1n4w6i8pa50jcs0sii-python3.8-nix-gui-0.1.0/bin/.nix-gui-wrapped", line 9, in <module>
    sys.exit(main())
  File "/nix/store/q3yrkldj3jh44z1n4w6i8pa50jcs0sii-python3.8-nix-gui-0.1.0/lib/python3.8/site-packages/nixui/gui.py", line 66, in main
    statemodel = state_model.StateModel()
  File "/nix/store/q3yrkldj3jh44z1n4w6i8pa50jcs0sii-python3.8-nix-gui-0.1.0/lib/python3.8/site-packages/nixui/state_model.py", line 14, in __init__
    for opt in api.get_options_dict().keys()
  File "/nix/store/q3yrkldj3jh44z1n4w6i8pa50jcs0sii-python3.8-nix-gui-0.1.0/lib/python3.8/site-packages/nixui/api.py", line 13, in get_options_dict
    res = json.load(open('./release_out/share/doc/nixos/options.json'))
FileNotFoundError: [Errno 2] No such file or directory: './release_out/share/doc/nixos/options.json'

What should I do to be able to run it ?

Convert api.py to configuration_interface.py

api.py doesn't handle dependency injection and reads os.environ['CONFIGURATION_PATH'] to determine where to read/write option data. configuration_interface.py should be a class-based reader instantiated by StateModel which is injected with the path of a module.

Diff and Save Functionality

Enable functionality for two toolbar actions:

  • save toolbar button: Diff view with "Save" button
    • until v1.0, changes will be saved to ~/.config/nix-gui/output/<full module path>
  • diff toolbar button: Diff view which can be escaped

Components:

  • diff viewer: scrollable table showing option, old value, new value
  • save: because nix-gui is unstable, it will not save to NIXGUI_CONFIGURATION_PATH, rather it will save to ~/.config/nix-gui, therefore we must
    • check whether NIXGUI_CONFIGURATION_PATH_CAN_BE_CORRUPTED is set to 1, otherwise (always do this)
      • save a cached version to ~/.config/nix-gui/output/<full module path> upon startup of nix-gui
      • reset the configuration path to the above
    • implement field literal -> expression string for each field
    • use ast.py to save to the configuration path

attempt to call something which is not a function but a set

Hi,

From patches to patches, it progresses =D

I tried again, and it failed again :

CONFIGURATION_PATH=/etc/nixos/configuration.nix nixFlakes run github:lapp0/nix-gui
warning: ignoring the user-specified setting 'experimental-features', because it is a restricted setting and you are not a trusted user
Traceback (most recent call last):
  File "/nix/store/1wb8vhks5nhai197qjy3jwv0s6k181gf-python3.8-nix-gui-0.1.0/bin/.nix-gui-wrapped", line 9, in <module>
    sys.exit(main())
  File "/nix/store/1wb8vhks5nhai197qjy3jwv0s6k181gf-python3.8-nix-gui-0.1.0/lib/python3.8/site-packages/nixui/main.py", line 10, in main
    statemodel = state_model.StateModel()
  File "/nix/store/1wb8vhks5nhai197qjy3jwv0s6k181gf-python3.8-nix-gui-0.1.0/lib/python3.8/site-packages/nixui/state_model.py", line 26, in __init__
    self.current_values = api.get_option_values_map()
  File "/nix/store/1wb8vhks5nhai197qjy3jwv0s6k181gf-python3.8-nix-gui-0.1.0/lib/python3.8/site-packages/nixui/utils/copy_decorator.py", line 6, in fn
    return copy.copy(wrapped(*args, **kwargs))
  File "/nix/store/1wb8vhks5nhai197qjy3jwv0s6k181gf-python3.8-nix-gui-0.1.0/lib/python3.8/site-packages/nixui/options/api.py", line 75, in get_option_values_map
    for option, option_data in get_option_data().items()
  File "/nix/store/1wb8vhks5nhai197qjy3jwv0s6k181gf-python3.8-nix-gui-0.1.0/lib/python3.8/site-packages/nixui/utils/copy_decorator.py", line 6, in fn
    return copy.copy(wrapped(*args, **kwargs))
  File "/nix/store/1wb8vhks5nhai197qjy3jwv0s6k181gf-python3.8-nix-gui-0.1.0/lib/python3.8/site-packages/nixui/options/api.py", line 48, in get_option_data
    configured_values = {'.'.join(k): v for k, v in parser.get_all_option_values(os.environ['CONFIGURATION_PATH']).items()}
  File "/nix/store/1wb8vhks5nhai197qjy3jwv0s6k181gf-python3.8-nix-gui-0.1.0/lib/python3.8/site-packages/nixui/options/parser.py", line 10, in get_all_option_values
    for attr_loc, attr_data in nix_eval.get_modules_defined_attrs(module_path).items():
  File "/nix/store/1wb8vhks5nhai197qjy3jwv0s6k181gf-python3.8-nix-gui-0.1.0/lib/python3.8/site-packages/nixui/options/nix_eval.py", line 59, in get_modules_defined_attrs
    leaves = nix_instantiate_eval(leaves_expr_template.substitute(module_path=module_path), strict=True)
  File "/nix/store/1wb8vhks5nhai197qjy3jwv0s6k181gf-python3.8-nix-gui-0.1.0/lib/python3.8/site-packages/nixui/options/nix_eval.py", line 21, in nix_instantiate_eval
    res = subprocess.check_output(cmd, stderr=log_pipe)
  File "/nix/store/66fbv9mmx1j4hrn9y06kcp73c3yb196r-python3-3.8.9/lib/python3.8/subprocess.py", line 415, in check_output
    return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
  File "/nix/store/66fbv9mmx1j4hrn9y06kcp73c3yb196r-python3-3.8.9/lib/python3.8/subprocess.py", line 516, in run
    raise CalledProcessError(retcode, process.args,
subprocess.CalledProcessError: Command '['nix-instantiate', '--eval', '-E', '\nlet\n  config = import /etc/nixos/configuration.nix {config = {}; pkgs = import <nixpkgs> {}; lib = import <nixpkgs/lib>;};\n  closure = builtins.tail (builtins.genericClosure {\n    startSet = [{ key = builtins.toJSON []; value = {value = config;}; }];\n    operator = {key, value}: builtins.filter (x: x != null) (\n      if\n        builtins.isAttrs value.value\n      then\n        builtins.map (new_key:\n          let\n            pos = (builtins.unsafeGetAttrPos new_key value.value);\n          in\n            if\n              builtins.isNull pos || (pos.file != builtins.toString "/etc/nixos/configuration.nix")\n            then null\n            else {\n              key = builtins.toJSON ((builtins.fromJSON key) ++ [new_key]);\n              value = {\n                value = builtins.getAttr new_key value.value;\n                inherit pos;\n              };\n            }\n        ) (builtins.attrNames value.value)\n      else []\n    );\n  });\n  leaves = builtins.filter (x: !(builtins.isAttrs x.value.value)) closure;\nin\nbuiltins.map (x: {name = builtins.fromJSON x.key; position = x.value.pos;}) leaves\n    ', '--json', '--strict']' returned non-zero exit status 1.

I copied the executed script in the command line and got this error

nix-shell script.nix
error: attempt to call something which is not a function but a set, at /tmp/script.nix:2:12
(use '--show-trace' to show detailed location information)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.