From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Andrew Hyatt Newsgroups: gmane.emacs.help Subject: Re: Programming Emacs visually with semantic triplets Date: Sat, 21 Jan 2023 16:56:51 -0500 Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="29291"; mail-complaints-to="usenet@ciao.gmane.io" To: Eduardo Ochs , Help GNU Emacs , Andrew Hyatt Original-X-From: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane-mx.org@gnu.org Mon Jan 23 15:25:35 2023 Return-path: Envelope-to: geh-help-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1pJxlP-0007OS-GX for geh-help-gnu-emacs@m.gmane-mx.org; Mon, 23 Jan 2023 15:25:35 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pJxka-00064Y-2N; Mon, 23 Jan 2023 09:24:45 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pJLrK-0001vX-Pk for help-gnu-emacs@gnu.org; Sat, 21 Jan 2023 16:57:10 -0500 Original-Received: from mail-ej1-x635.google.com ([2a00:1450:4864:20::635]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pJLrE-0001rc-SM for help-gnu-emacs@gnu.org; Sat, 21 Jan 2023 16:57:09 -0500 Original-Received: by mail-ej1-x635.google.com with SMTP id vw16so22047210ejc.12 for ; Sat, 21 Jan 2023 13:57:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=to:subject:message-id:date:from:in-reply-to:references:mime-version :from:to:cc:subject:date:message-id:reply-to; bh=tWS/2qVRasM7D8T9iPaztXlelBqMFAaEU3fnwXrty+k=; b=qoP8dmVFWUTgg54zEdpA833+zBE7yP5PUHXShwzS+a0DoIYhPl0Dt2o4D0fJroiHx8 I5MJyOumyecYKiJEVqEZsIbSmW56jIK3Bp8i1wGsiKpdYt6D38WzIsyXgZHszj3GfCLQ bmelqnMVr+uEe8423G8FEWDwiPGvON830KvsBLS7vkJF8yrqbtV9aCnpJzSOix0DZhWQ 0LcNCWGTHQD0KkHcTcaceu8Ga4raNbwqFSzHC8xbQYfB2yj5LmHoT3OFoN0HD9xdfgY0 DR65cC8ksKN602lrvCxntspiSPYNQ+xq13h1GkGQYk1KOho0A1wejz2od7U0QL7IgWN3 1SeA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=to:subject:message-id:date:from:in-reply-to:references:mime-version :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=tWS/2qVRasM7D8T9iPaztXlelBqMFAaEU3fnwXrty+k=; b=sUmgMeT/VgAOhlpexN/dF0dRXUjQaZbaHKcixtypqSQlJvnvHR9VehKzVQvwG55Jhz EubWEeWe3v2l6tCBdseDM8S0n4n/E6GHi51DkZwYzk/wQFJV/VYyM3LykeK/CI2RMeOt D7Egwd0HaQprNG56jczEweAUlSC6xjzp7sVVdyvf+hb+YN1C5Z3d8abViL5hbMrYgen0 JUPaSQch0MDWFKNenKjya7s19iF49HcuG6QPcNMU/nfF0lts92w/g71Q+1Xc6cwkRzvW mxoQ+cgWGgrCjNWa/nmvawWOU0UE2Nz8NVy0GbEmMybuBVUneRrRpXosktU7tcJa9CtU Rs+A== X-Gm-Message-State: AFqh2krybmePe8Zy5lBIU+2LVYZ62AeP+hdu3Z5xkBJbbic3oEpZfxn8 E1/MOYXoja2viPEmz6kfvmKwlujxwLstB60zbuo= X-Google-Smtp-Source: AMrXdXupCuhfSLQ7E7jZ/1QGBLbVeJPJb44xDJVk56mLKTYYJaAP+Q7RdAL5qPbOQxG3eUDhTV1zwTaKcujW90vlUDg= X-Received: by 2002:a17:906:df49:b0:7c1:908e:709e with SMTP id if9-20020a170906df4900b007c1908e709emr1581123ejc.414.1674338222618; Sat, 21 Jan 2023 13:57:02 -0800 (PST) In-Reply-To: Received-SPF: pass client-ip=2a00:1450:4864:20::635; envelope-from=ahyatt@gmail.com; helo=mail-ej1-x635.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Mon, 23 Jan 2023 09:24:39 -0500 X-Content-Filtered-By: Mailman/MimeDel 2.1.29 X-BeenThere: help-gnu-emacs@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Users list for the GNU Emacs text editor List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.help:142517 Archived-At: These are interesting ideas. In a sense, it reminds me of the relation of editing in emacs, creating macros, vs elisp programming. This is kind of a way to get some useful functionality without programming. What does success look like to you? I suspect if you want to put an interesting and cool showcase of these ideas out there, that's definitely possible, and that may lead to interesting things. However, I think tools to create applications tend to be niche, and most users want to have something immediately useful which can then be added to. That's why I'm going with a more app-driven approach to some of these ideas in ekg. On Sat, Jan 21, 2023 at 3:09 PM Jean Louis wrote: > * Eduardo Ochs [2023-01-21 13:40]: > > Hi Jean, > > do you have tools that show the Lisp code behind each button and that > show > > pretty-printed versions of the main data structures? Can you send us > > screenshots of that? Some people - like me =3D/ - understand these thin= gs > > much more easily when they see how a prototype was implemented... > > I create my tables semi-automagically, by using function: > > (defun rcd-db-create-table (table pg) > "Create TABLE with database handle PG." > (let* ((table (or table (rcd-ask-get "New database table name: "))) > (sql (format "CREATE TABLE %s ( > %s_id SERIAL NOT NULL PRIMARY KEY, > %s_uuid UUID NOT NULL DEFAULT gen_random_uuid() > UNIQUE, > %s_datecreated TIMESTAMP WITH TIME ZONE DEFAULT > CURRENT_TIMESTAMP NOT NULL, > %s_datemodified TIMESTAMP WITH TIME ZONE, > %s_usercreated TEXT NOT NULL DEFAULT current_user, > %s_usermodified TEXT NOT NULL DEFAULT current_user, > %s_name TEXT NOT NULL, > %s_description TEXT)" > table table table table table table table table > table))) > (rcd-sql sql pg))) > > Which takes care of nice structure, so each column name speaks about > table as "predicates_uuid" clearly belong to table "predicates". This > I have learnt from Gedafe: > > GeDaFe - PostgreSQL Generic Database Interface: > http://gedafe.github.io/doc/gedafe-sql.en.html > > And I keep following Gedafe design, as all of my stuff worked and will > still work in Gedafe. > > For the concept of triplets, there are just few tables, one is > "predicates". > > Table > "public.predicates" > > =E2=94=8C=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=AC=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=AC=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=AC=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=AC=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=90 > =E2=94=82 Column =E2=94=82 Type =E2= =94=82 Collation =E2=94=82 > Nullable =E2=94=82 Default =E2= =94=82 > > =E2=94=9C=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=BC=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=BC=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=BC=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=BC=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=A4 > =E2=94=82 predicates_id =E2=94=82 integer =E2= =94=82 =E2=94=82 not > null =E2=94=82 nextval('predicates_predicates_id_seq'::regclass) =E2=94= =82 > =E2=94=82 predicates_uuid =E2=94=82 uuid =E2= =94=82 =E2=94=82 not > null =E2=94=82 gen_random_uuid() =E2=94= =82 > =E2=94=82 predicates_datecreated =E2=94=82 timestamp with time zone =E2= =94=82 =E2=94=82 not > null =E2=94=82 CURRENT_TIMESTAMP =E2=94= =82 > =E2=94=82 predicates_datemodified =E2=94=82 timestamp with time zone =E2= =94=82 =E2=94=82 > =E2=94=82 =E2=94=82 > =E2=94=82 predicates_usercreated =E2=94=82 text =E2= =94=82 =E2=94=82 not > null =E2=94=82 CURRENT_USER =E2=94= =82 > =E2=94=82 predicates_usermodified =E2=94=82 text =E2= =94=82 =E2=94=82 not > null =E2=94=82 CURRENT_USER =E2=94= =82 > =E2=94=82 predicates_name =E2=94=82 text =E2= =94=82 =E2=94=82 not > null =E2=94=82 '>>>UNKNOWN<<<'::text =E2=94= =82 > =E2=94=82 predicates_description =E2=94=82 text =E2= =94=82 =E2=94=82 > =E2=94=82 =E2=94=82 > > =E2=94=94=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=B4=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=B4=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=B4=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=B4=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=98 > Indexes: > "predicates_pkey" PRIMARY KEY, btree (predicates_id) > "predicates_predicates_name_idx" UNIQUE, btree (predicates_name) > "predicates_predicates_uuid_key" UNIQUE CONSTRAINT, btree > (predicates_uuid) > Triggers: > insert_username_predicates BEFORE INSERT OR UPDATE ON predicates FOR > EACH ROW EXECUTE FUNCTION insert_username('predicates_usermodified') > predicates_moddatetime BEFORE UPDATE ON predicates FOR EACH ROW > EXECUTE FUNCTION moddatetime('predicates_datemodified') > > > Another one is "sobjects", which mean "subjects or objects", as why > have it separate? > > > Table "public.sobjects" > > =E2=94=8C=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =AC=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=AC=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=AC=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =AC=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=90 > =E2=94=82 Column =E2=94=82 Type =E2=94= =82 Collation =E2=94=82 Nullable > =E2=94=82 Default =E2=94=82 > > =E2=94=9C=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =BC=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=BC=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=BC=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =BC=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=A4 > =E2=94=82 sobjects_id =E2=94=82 integer =E2=94= =82 =E2=94=82 not null > =E2=94=82 nextval('sobjects_sobjects_id_seq'::regclass) =E2=94=82 > =E2=94=82 sobjects_uuid =E2=94=82 uuid =E2=94= =82 =E2=94=82 not null > =E2=94=82 gen_random_uuid() =E2=94=82 > =E2=94=82 sobjects_datecreated =E2=94=82 timestamp with time zone =E2=94= =82 =E2=94=82 not null > =E2=94=82 CURRENT_TIMESTAMP =E2=94=82 > =E2=94=82 sobjects_datemodified =E2=94=82 timestamp with time zone =E2=94= =82 =E2=94=82 > =E2=94=82 =E2=94=82 > =E2=94=82 sobjects_usercreated =E2=94=82 text =E2=94= =82 =E2=94=82 not null > =E2=94=82 CURRENT_USER =E2=94=82 > =E2=94=82 sobjects_usermodified =E2=94=82 text =E2=94= =82 =E2=94=82 not null > =E2=94=82 CURRENT_USER =E2=94=82 > =E2=94=82 sobjects_name =E2=94=82 text =E2=94= =82 =E2=94=82 not null > =E2=94=82 '>>>UNKNOWN<<<'::text =E2=94=82 > =E2=94=82 sobjects_description =E2=94=82 text =E2=94= =82 =E2=94=82 > =E2=94=82 =E2=94=82 > > =E2=94=94=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =B4=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=B4=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=B4=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =B4=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=98 > Indexes: > "sobjects_pkey" PRIMARY KEY, btree (sobjects_id) > "sobjects_sobjects_uuid_key" UNIQUE CONSTRAINT, btree (sobjects_uuid) > Triggers: > insert_username_sobjects BEFORE INSERT OR UPDATE ON sobjects FOR EACH > ROW EXECUTE FUNCTION insert_username('sobjects_usermodified') > sobjects_moddatetime BEFORE UPDATE ON sobjects FOR EACH ROW EXECUTE > FUNCTION moddatetime('sobjects_datemodified') > > The whole concept is based on UUID which is not a primary key, which > is not relational database conformant, but it gives that way some > flexibility. > > Then there is this table: > > Table "public.uuid2uui= d" > > =E2=94=8C=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=AC=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=AC=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=AC=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=AC=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=90 > =E2=94=82 Column =E2=94=82 Type =E2= =94=82 Collation =E2=94=82 Nullable > =E2=94=82 Default =E2=94=82 > > =E2=94=9C=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=BC=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=BC=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=BC=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=BC=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=A4 > =E2=94=82 uuid2uuid_id =E2=94=82 integer =E2= =94=82 =E2=94=82 not null > =E2=94=82 nextval('uuid2uuid_uuid2uuid_id_seq'::regclass) =E2=94=82 > =E2=94=82 uuid2uuid_uuid =E2=94=82 uuid =E2= =94=82 =E2=94=82 not null > =E2=94=82 gen_random_uuid() =E2=94=82 > =E2=94=82 uuid2uuid_datecreated =E2=94=82 timestamp with time zone =E2= =94=82 =E2=94=82 not null > =E2=94=82 CURRENT_TIMESTAMP =E2=94=82 > =E2=94=82 uuid2uuid_datemodified =E2=94=82 timestamp with time zone =E2= =94=82 =E2=94=82 > =E2=94=82 =E2=94=82 > =E2=94=82 uuid2uuid_usercreated =E2=94=82 text =E2= =94=82 =E2=94=82 not null > =E2=94=82 CURRENT_USER =E2=94=82 > =E2=94=82 uuid2uuid_usermodified =E2=94=82 text =E2= =94=82 =E2=94=82 not null > =E2=94=82 CURRENT_USER =E2=94=82 > =E2=94=82 uuid2uuid_description =E2=94=82 text =E2= =94=82 =E2=94=82 > =E2=94=82 ''::text =E2=94=82 > =E2=94=82 uuid2uuid_subjects =E2=94=82 uuid =E2= =94=82 =E2=94=82 not null > =E2=94=82 =E2=94=82 > =E2=94=82 uuid2uuid_predicates =E2=94=82 uuid =E2= =94=82 =E2=94=82 not null > =E2=94=82 =E2=94=82 > =E2=94=82 uuid2uuid_objects =E2=94=82 uuid =E2= =94=82 =E2=94=82 not null > =E2=94=82 =E2=94=82 > > =E2=94=94=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=B4=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=B4=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=B4=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=B4=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80= =E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2= =94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94=80=E2=94= =80=E2=94=98 > Indexes: > "uuid2uuid_pkey" PRIMARY KEY, btree (uuid2uuid_id) > "uuid2uuid_uuid2uuid_subjects_uuid2uuid_predicates_uuid2uuid_idx" > UNIQUE, btree (uuid2uuid_subjects, uuid2uuid_predicates, uuid2uuid_object= s) > "uuid2uuid_uuid2uuid_uuid_key" UNIQUE CONSTRAINT, btree > (uuid2uuid_uuid) > > How I see the issue at hand, that becomes enough to reference anything > to anything. > > If I have table "people" with Eduardo entry there, it has UUID: > EBD4E7DA-2321-4E1C-97CA-A7F659015AD6, and then I can either: > > - make new entry in "sobjects" and create new UUID holding Eduardo's > UUID: EBD4E7DA-2321-4E1C-97CA-A7F659015AD6 > > - then I can tell "Eduardo" with underlying UUID, "is" as predicate, > "programmer" with "programmer" also having its own UUID > > That is stored in "uuid2uuid" table: > > Entry does not look human friendly: > > -[ RECORD 49 ]---------+------------------------------------- > uuid2uuid_id | 49 > uuid2uuid_uuid | 764114e5-2d7a-4b9a-b1b0-a5719e6f3468 > uuid2uuid_datecreated | 2023-01-21 19:26:17.890422+03 > uuid2uuid_datemodified | > uuid2uuid_usercreated | maddox > uuid2uuid_usermodified | maddox > uuid2uuid_description | > uuid2uuid_subjects | fe54313c-7472-4498-a993-1b4ac949ff5c > uuid2uuid_predicates | 6effc368-b66c-4216-a230-6916e3bfdc70 > uuid2uuid_objects | df35a22c-725e-4202-b79e-9ab4a147bff7 > > Though that gives flexibility, as UUID does not need to reference any > table in underlying database, it can reference any UUID, inside or > outside of the database. > > There is more to implement. Functions are here: > > ;;; Semantic Triplets > > ;; This below is more fundamental function, it just creates new entry > ;; and returned it's ID for further update. And it demands that all > ;; entries have their default values, like if there is no name, the > ;; name will appear as '>>>UNKNOWN<<<' which demands updating it. > > (defun rcd-db-table-insert-default-values (table db) > "Insert default values into TABLE with DB handle." > (rcd-sql-first (format "INSERT INTO %s DEFAULT VALUES RETURNING %s_id" > table table) db)) > > ;; This below is function to get the primary key of the entry by using > ;; TABLE and UUID. I don't use UUID's as primary key as it is not > ;; convenient, but many entries do have UUID to be searchable without > ;; being referenced. > > ;; Below works because all tables have conformant format, like > ;; "people" will have "people_uuid", and "people_id", and because of > ;; the format, magic is possible just as explained in Gedafe > ;; documents. It becomes possible to prepare the underlying structure > ;; and to have EDIT, DUPLICATE, DELETE functions automatically in GUI > ;; or Emacs interface, or WWW interface. > > (defun rcd-db-uuid-by-id (table id db) > "Return UUID for TABLE with ID and DB handle." > (rcd-sql-first (format "SELECT %s_uuid FROM %s WHERE %s_id =3D %s" tabl= e > table table id) db)) > > ;; Of course, as not to interfer with other modes, it is better to > ;; create new mode, which can hold kew bindings. The text mode or > ;; buffer is used as menu system with buttons, similar like Hypertext. > > (define-derived-mode rcd-triplets-view-mode org-mode > "RCD Notes Triplets View Mode" > "Semantic Triplets in RCD Notes") > > ;; This is new experiment, as I am tired of writing always different > ;; function in key bindings, so I have decided to write always some > ;; function, like in this case`rcd-triplets-add-new' which does > ;; different job depending of the key binding. > > (keymap-set rcd-triplets-view-mode-map "a s" #'rcd-triplets-add-new) > (keymap-set rcd-triplets-view-mode-map "a p" #'rcd-triplets-add-new) > (keymap-set rcd-triplets-view-mode-map "a o" #'rcd-triplets-add-new) > (keymap-set rcd-triplets-view-mode-map "q" #'quit-window) > > ;; This is only to add new "sobject" which is subject or object. But > ;; the main triplet table named "uuid2uuid" above does not really > ;; require table "sobjects" as it will accept any UUIDs, referencing > ;; to other tables, or even to objects with UUID outside of database > ;; space. > > (defun rcd-triplets-sobject-new () > "Add new subject or object and return it's UUID." > (interactive) > (let ((id (rcd-db-table-insert-default-values "sobjects" cf-db)) > (name (rcd-ask-get "Add new subject or object: "))) > (rcd-db-update-entry "sobjects" "sobjects_name" id name cf-db) > (rcd-db-uuid-by-id "sobjects" id cf-db))) > > ;; In similar way, this function adds new predicate. There are > ;; depending functions, like `rcd-db-update-entry' > > (defun rcd-triplets-predicate-new () > "Add new predicate and return it's UUID." > (interactive) > (let ((id (rcd-db-table-insert-default-values "predicates" cf-db)) > (name (rcd-ask-get "Add new predicate: "))) > (rcd-db-update-entry "predicates" "predicates_name" id name cf-db) > (rcd-db-uuid-by-id "predicates" id cf-db))) > > ;; This is helper function to find last key pressed. > > (defun rcd-last-key () > "Return last key." > (elt (seq-reverse (recent-keys)) 0)) > > ;; This function is for adding entries, like objects or subjects, > predicates. > > (defun rcd-triplets-add-new () > "Add new subject, predicate or object. > > Function may be called interactively, or as part of key bindings. > > For last key `s' add new subject. > For last key `p' add new predicate. > For last key `o' add new predicate." > (interactive) > ;; I use here the helper function to recognize what was last key > ;; pressed, as not to mess to much with keymap settings. Rather I > ;; keep decision making in this function. > (let* ((key (rcd-last-key)) > (new-id > (cond ((and (numberp key) (=3D ?s key)) (rcd-triplets-sobject-n= ew)) > ((and (numberp key) (=3D ?p key)) > (rcd-triplets-predicate-new)) > ((and (numberp key) (=3D ?o key)) (rcd-triplets-sobject-n= ew)) > ;; but if no corresponding last key is found, then I > ;; offer to user choice what to add instead. > (t (let ((choice (rcd-choose '("Subject or Object" > "Predicate")))) > (cond ((string-match "Subject" choice) > (rcd-triplets-subject-new)) > ((string=3D "Predicate" choice) > (rcd-triplets-predicate-new)) > (t (user-error "Cannot handle choice")))))))) > ;; And then the list of objects is re-displayed. > (cond ((and (numberp key) (=3D ?s key)) (rcd-triplets-db-list "sobjec= ts" > new-id)) > ((and (numberp key) (=3D ?p key)) (rcd-triplets-db-list > "predicates" new-id)) > ((and (numberp key) (=3D ?o key)) (rcd-triplets-db-list "sobjec= ts" > new-id))))) > > ;; This is initiating the buffer with proper mode. > > (defun rcd-triplets-buffer (buffer) > (unless (buffer-live-p (get-buffer buffer)) > (generate-new-buffer buffer)) > (set-buffer buffer) > (erase-buffer) > (display-buffer buffer) > (rcd-triplets-view-mode)) > > ;; Header function with buttons, you will recognize these functions > ;; from previous discussion. > > (defun rcd-triplets-header-insert () > (insert "\n RCD Notes =E2=AD=90 Semantic Triplets\n\n ") > (rcd-button-insert "[ADD]" (lambda (_) (rcd-triplets-new))) > (insert " ") > (rcd-button-insert "[TRIPLETS]" #'rcd-triplets-list) > (insert " ") > (rcd-button-insert "[SUBJECTS or OBJECTS]" > #'rcd-triplets-db-list-sobjects) > (insert " ") > (rcd-button-insert "[PREDICATES]" #'rcd-triplets-db-list-predicates) > (insert "\n\n")) > > ;; I have generalized this function to us both "subjects" and > ;; "predicates", so it works, it lists the items in the buffer. And it > ;; generates "[edit]" button to rename the object or predicate. > > (defun rcd-triplets-db-list (table &optional new-id) > (let* ((sql (format "SELECT %s_id, %s_uuid, %s_name > FROM %s > ORDER BY %s_id" > table table table table table)) > (items (rcd-sql-list sql cf-db)) > (width (format "%s" (rcd-db-column-width table (format "%s_id" > table) cf-db))) > (buffer (format "*RCD Notes: All %s for Semantic Triplets*" > table))) > (rcd-triplets-buffer buffer) > (rcd-triplets-header-insert) > (insert > (rcd-report-underlined > (upcase table) > (with-temp-buffer > (while items > (let* ((item (pop items)) > (id (nth 0 item)) > (uuid (nth 1 item)) > (name (nth 2 item))) > (insert (format (concat "%0" width "d. ") id)) > (rcd-button-insert > "[edit]" > (lambda (_) > (rcd-db-edit-entry table (concat table "_name") id cf-db) > (rcd-triplets-db-list table id))) > (insert " " name) > (insert "\n"))) > (buffer-string)))) > (cond (new-id > (goto-char (point-min)) > (search-forward-regexp (format "^%s. " new-id) nil t)) > (t (goto-char (point-min)) > (forward-line 3))))) > > ;; This is extensible function, for now it looks for the name in 2 > ;; tables like "sobjects" or "predicates", or if name is not > ;; available, it constructs name of the full triplet. There is more > ;; work to do, as if UUID belongs to people, then person's name shall > ;; appear, if it belongs to document, document's name should appear, > ;; and so on for many other tables in the database. > > (defun rcd-triplets-name-by-uuid (uuid) > (let* ((find-uuid (lambda (table uuid) > (rcd-db-get-entry-where > table > (format "%s_name" table) > (format "%s_uuid =3D %s" table (sql-escape-string > uuid)) > cf-db))) > (names (mapcar (lambda (table) (funcall find-uuid table uuid)) > '("sobjects" "predicates"))) > (names (delq nil names)) > (name (car names))) > (cond (name name) > (t (rcd-triplets-return-triplet uuid))))) > > ;; For example this function below, gives following: > ;; (rcd-triplets-name-by-uuid "f26d9e92-ed61-4281-a27e-668b76daa5e2") =E2= =9E=9C > "known universe is/are inside [2] of/from unknown universe [3]" > > ;; This is similar function as to list items, just specifically for > ;; all of the triplets in the buffer. > > ;; It offers 2 buttons, like [subject] and [object] which gives to > ;; user possibility to take whole triplet and make it object or > ;; subject with some predicate. > > ;; That enables definitions like: > > ;; Emacs Lisp is/are programming language > ;; help to human > ;; Emacs Lisp is/are help to human [41] > ;; programming language has/have function > ;; programming language is/are language > ;; English is/are language > ;; verb is/are predicate > ;; run is/are verb > ;; programming language has/have function [43] may be run > ;; language has/have verb > > ;; Doing it gives me some ideas, as that way it is possible to quickly > ;; define concepts. Triplet of basic understanding builds on other > ;; triplets of basic understandings. It can build into "contact > ;; entry", which by semantics "may require" other information like > ;; "phone number", or "e-mail" address, and by designing > ;; relationships, one can then say that "contact entry" is a function > ;; (and that must be programmed), and that function shall ask for > ;; other entries, and those can be parsed automatically. So I think > ;; that by parsing semi-visually and interactively defined meanings it > ;; is possible to program computer in somewhat easier manner than by > ;; writing code. At least for some basic applications, let us say for > ;; invoices, or notes, tasks. > > (defun rcd-triplets-list (&optional _) > (interactive) > (let* ((triplets (rcd-sql-list > "SELECT uuid2uuid_id, uuid2uuid_uuid, > uuid2uuid_subjects, uuid2uuid_predicates, uuid2uuid_objects > FROM uuid2uuid" > cf-db)) > (width (rcd-db-column-width "uuid2uuid" "uuid2uuid_id" cf-db)) > (buffer "*RCD Notes: Semantic Triplets*")) > (rcd-triplets-buffer buffer) > (rcd-triplets-header-insert) > (insert > (rcd-report-underlined > "Semantic Triplets" > (with-temp-buffer > (while triplets > (let* ((triplet (pop triplets)) > (id (nth 0 triplet)) > (uuid (nth 1 triplet)) > (subject (nth 2 triplet)) > (subject-name (rcd-triplets-name-by-uuid subject)) > (predicate (nth 3 triplet)) > (predicate-name (rcd-triplets-name-by-uuid predicate)) > (object (nth 4 triplet)) > (object-name (rcd-triplets-name-by-uuid object))) > (rcd-button-insert > "[subject]" > (lambda (_) > (rcd-triplets-new uuid))) > (insert " ") > (rcd-button-insert > "[object]" > (lambda (_) > (rcd-triplets-new nil nil uuid))) > (insert " " subject-name " " predicate-name " " object-name) > (insert "\n"))) > (buffer-string)))) > (goto-char (point-min)))) > > ;; (rcd-triplets-name-by-uuid "f26d9e92-ed61-4281-a27e-668b76daa5e2") =E2= =9E=9C > "known universe is/are inside [2] of/from unknown universe [3]" > > ;; (rcd-triplets-return-triplet "764114e5-2d7a-4b9a-b1b0-a5719e6f3468") = =E2=9E=9C > "language has/have verb [49]" > > ;; This is function that writes representation of triplet. I think of > ;; expanding representation by adding correct singular, and plural > ;; forms, as that way I will avoid having "is/are", but will have > ;; proper "is" or "are" as predicate > > (defun rcd-triplets-return-triplet (uuid) > (let* ((triplet (rcd-sql-list-first "SELECT uuid2uuid_subjects, > uuid2uuid_predicates, uuid2uuid_objects > FROM uuid2uuid > WHERE uuid2uuid_uuid =3D $1" > cf-db uuid)) > (id (cadr (rcd-db-id-by-uuid uuid))) > (subject (nth 0 triplet)) > (subject-name (rcd-triplets-name-by-uuid subject)) > (predicate (nth 1 triplet)) > (predicate-name (rcd-triplets-name-by-uuid predicate)) > (object (nth 2 triplet)) > (object-name (rcd-triplets-name-by-uuid object))) > (format "%s %s %s [%s]" subject-name predicate-name object-name id))) > > ;; This one just list the "sobject" items in buffer. Must have "_" > ;; optional argument to be used as button. > > (defun rcd-triplets-db-list-sobjects (&optional _) > (interactive) > (rcd-triplets-db-list "sobjects")) > > ;; List predicates in buffer. > > (defun rcd-triplets-db-list-predicates (&optional _) > (interactive) > (rcd-triplets-db-list "predicates")) > > ;; Select one of "sobjects" or "prdicates" by using completing read. > > (defun rcd-triplets-sobject-select (&optional prompt) > (rcd-db-combo-selection "sobjects" (or prompt "Select subject or object= : > "))) > > (defun rcd-triplets-predicate-select (&optional prompt) > (rcd-db-combo-selection "predicates" (or prompt "Select predicate: "))) > > ;; Record triplet, this one accepts UUID only and eventually > ;; description. You never know why some relation shall be described, > ;; it is note about the note. This is lower level function. > > (defun rcd-triplets-record-triplet (subject-uuid predicate-uuid > object-uuid &optional description) > (let ((description (or description ""))) > (rcd-sql-first > "INSERT INTO uuid2uuid (uuid2uuid_subjects, uuid2uuid_predicates, > uuid2uuid_objects, uuid2uuid_description) > VALUES ($1, $2, $3, $4) > RETURNING uuid2uuid_id" > cf-db subject-uuid predicate-uuid object-uuid description))) > > ;; This is higher level function to record new triplet. UUID can be > ;; anything, what if it is other triplet? Other database and table > ;; UUID reference? It could be Org reference as well. > > (defun rcd-triplets-new (&optional subject-uuid predicate-uuid object-uui= d > description) > (interactive) > (let* ((subject (unless subject-uuid (rcd-triplets-sobject-select > "Select subject: "))) > (subject-uuid (or subject-uuid (rcd-db-uuid-by-id "sobjects" > subject cf-db))) > (predicate (unless predicate-uuid > (rcd-triplets-predicate-select))) > (predicate-uuid (or predicate-uuid (rcd-db-uuid-by-id > "predicates" predicate cf-db))) > (object (unless object-uuid (rcd-triplets-sobject-select "Select > object: "))) > (object-uuid (or object-uuid (rcd-db-uuid-by-id "sobjects" objec= t > cf-db))) > (description (rcd-ask "Description: "))) > (rcd-triplets-record-triplet subject-uuid predicate-uuid object-uuid > description))) > > There is more to expand, I have to continue "teaching" computer as to > understand how to implement automated programming functions. It may > involve injecting basic functions in the database, which I already do > with "types" of objects, if object is of PDF type, then I let the "PDF > type" decide by itself how to open PDF, and not that I put it in the > code. That way user has option to change how to open PDF, without > (much) coding. > > I am thinking that once it is defined well for example: > > - that task has created time > - that task must have name > - that task may be related to people > - that people is database table > - that task may have text body > > Then the final triplet may be defined to be actionable, something like > "task", and some triplets would become buttons. > > User would then be able to create own useful screen or search through > notes, and then click on button like "add task" to add, or later > delete, duplicate, etc. Some basic objects I have to define as > actionable, like screens, menu, etc. for program to be parsable and > executable, so that human can enter some data, and represent that data > in some way, or search through it, share it. > > I have only blurry idea that it may work that way. > > -- > Jean > > Take action in Free Software Foundation campaigns: > https://www.fsf.org/campaigns > > In support of Richard M. Stallman > https://stallmansupport.org/ >