Re: [O] lisp: scoping vars in repetitive defuns

2019-09-17 Thread Matt Price
On Tue, Sep 17, 2019 at 8:46 AM John Kitchin 
wrote:

> I don't totally understand what you are trying to do here.
>

I think the explanation was a little unclear!


> If this were Python, it sounds like you want some kind of class that
> stores a variable and reuses it several different functions? Something kind
> of similar to that in elisp is a closure, which is like what you described.
> For example, here, we define a variable a, and then define two functions
> that use it persistently.
>
>
> I think you can wrap this in a macro to make new functions, e.g.
>
> #+BEGIN_SRC emacs-lisp
> (defmacro f-maker (a)
>   `(lexical-let ((a ,a))
>  (defun f1 (x)
>(* a x))
>
>  (defun f2 (x)
>(+ a x
>
> (f-maker 3)
>
> (list (f1 2) (f2 2))
> #+END_SRC
>
> #+RESULTS:
> | 6 | 5 |
>
> This is basically what I want, except it turned out to be easier to just
wrap the body forms in a let *within*the function.  THis is what I came up
with:

#+BEGIN_SRC emacs-lisp

(defmacro dh-factory (name body  docstring)
"A helper macro that sets up the environment to simplify defining multiple
functions with the same environment variables. NAME will bcome the functin
name, BODY is a list containing the lisp forms specific to the function,
and DOCSTRING is an optional ... docstring.  NAME wil lbe wrapped in a
`let` statement setting all the remelvant variables."
  `(lexical-let (())
 (defun ,name ,()
   ,docstring
   (interactive)
   (let* ((gh (org-entry-get (point) "GITHUB"))
 (base (org-entry-get (point) "ORG_LMS_ASSIGNMENT_DIRECTORY"))
 (findFiles `( ,(concat "Reflection/" gh ".md") ,(concat
"students/" gh ".json")))
 (browseFiles `( "index.html" ))
 (testOutput "TestResults/testresults.html")
 (testCommand "MARKING=instructor npm test"))
 ,@body

(dh-factory dh-find-files
((dolist (f findFiles)
   (message "%s" (concat base "/" f))
   (if (file-exists-p (concat base "/" f))
   (find-file-other-window (concat base "/" f) )
 (message "File %s does not exist, not opening." f)))  )
"Open gradable files in Emacs windows")

(dh-factory dh-view
((loop for f in browseFiles
do
(browse-url-of-file (concat base "/" f 
"open viewable files in browser")

;; this one should really pass a variable to allow different branches! oh
well.
(dh-factory dh-status
((magit-status base)
 (let ((currentBranch (shell-command-to-string
   (format "cd %s && git rev-parse
--abbrev-ref HEAD" base) ))
   (currentCommit (shell-command-to-string
   (format "cd %s && git rev-parse HEAD"
base
   (magit-stash-worktree
(format "Stashed random files from %s after commit %s."
currentBranch currentCommit)))
 (magit-checkout (concat gh "-master")))
"Open a magit-status buffer and check out this student's branch
in the repo")


(dh-factory dh-tests
((let ((output))
(with-temp-buffer
   (message (concat "cd " base " ; npm test"))
   (setq output (shell-command-to-string (concat "cd " base " ;
npm test"
(message "WELL, sorta made it through: %s" output)
 (browse-url-of-file (concat base testOutput
"Run tests directly from macs and view output")


#+END_SRC

I quite like it, though it's a bit unwieldy not to have the the source code
available for edebug etc. It feels a little like having a namespace; I'm
not afraid of  polluting the global namespace, but I can use these symbol
names throughout the code I'm processing via the factory.

I'm not sure it's *all* that much more efficient though...

>
> There is also a class system you can probably use like this called eieio,
> Here is one approach to doing this.
>
> #+BEGIN_SRC emacs-lisp
> (require 'eieio)
>
> (defclass Grade ()
>   ((:a :initarg :a)))
>
> (cl-defmethod gf1 ((g Grade) x)
>   (* (oref g :a) x))
>
> (cl-defmethod gf2 ((g Grade) x)
>   (+ (oref g :a) x))
>
> (let ((G (Grade :a 3)))
>   (list (gf1 G 2) (gf2 G 2)))
> #+END_SRC
>
> #+RESULTS:
> | 6 | 5 |
>
> I would love to learn to use eieio but it feels like a bit of a jump.

>
> Finally, maybe the simplest thing to do is pass this information in as an
> argument, e.g. a plist or alist, or get them from a function that you only
> change in one place?
>

That might have been more sensible but this was pretty fun!

Thanks everyone for the help!



> On Tue, Sep 17, 2019 at 7:31 AM Matt Price  wrote:
>
>> I have a number of convenience functions define to help me with grading
>> assignments. As I go through the semester, i update all of these functions
>> modestly so that they'rehelpful for grading the current assignment.
>>
>> I big chunk of these simple 

[O] Bug: Org commit d07d8ff41 breaks square-brace links in recent Emacs. [9.2.6 (release_9.2.6-538-g23113f @ /home/kfogel/src/org-mode/lisp/)]

2019-09-17 Thread Karl Fogel
Hi.  It appears that commit d07d8ff4163 in Org Mode causes 
square-brace-enclosed links to display incorrectly.

The buggy behavior is simple to describe: if you write a link like this

  [[URL][LINK-TEXT]]

then URL will be displayed instead of LINK-TEXT (and LINK-TEXT goes unused: URL 
is still also given as the underlying link).

I haven't debugged this, but it seems to be caused by this commit in Org Mode:

> commit d07d8ff416373e5a4f2d91ed1d7f9cb3a80b8439
> Author: Max Mouratov 
> AuthorDate: Thu Aug 29 22:48:22 2019 +0500
> Commit: Nicolas Goaziou 
> CommitDate: Mon Sep 16 18:55:04 2019 +0200
> 
> Prevent loss of `re-search-forward' results
> 
> * org.el (org-activate-links): `match-beginning' and `match-end` should
> be called shortly after `re-search-forward'. Otherwise, they may return
> values corresponding to a different invocation of `re-search-forward'.
> 
> TINYCHANGE
> 
> M lisp/org.el

Here's how to verify

  1) Revert just commit d07d8ff41 in your Org Mode source tree
  2) 'make'
  3) 'make autoloads'
  4) Restart Emacs

With that commit reverted, links behave correctly.  When I restored the commit 
(and rebuilt, etc), links behaved incorrectly again.

This is all with the latest 'master' branch of Emacs (commit 746b20c237), with 
latest development Org Mode (commit 23113feb9a, which is only one commit beyond 
the suspect commit).

Best regards,
-Karl


Emacs  : GNU Emacs 27.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.11)
 of 2019-09-17
Package: Org mode version 9.2.6 (release_9.2.6-538-g23113f @ 
/home/kfogel/src/org-mode/lisp/)



[O] bug with emacs 26.3 and hyperlinks

2019-09-17 Thread Thomas Holst
Hello,

today I upgraded to emacs 26.3. and links don't show up correct anymore
with org-mode from git. The link is shown not the description.

Steps to reproduce:

=test.org=:
#+begin_src org
  [[http://www.google.com][A Test link]]
#+end_src

: emacs -Q --find-file="test.org"

All links are shown as described above.

=git bisect= shows following commit as root cause:

Author: Max Mouratov 

Date:   Thu Aug 29 22:48:22 2019 +0500

Prevent loss of `re-search-forward' results

* org.el (org-activate-links): `match-beginning' and `match-end` should
be called shortly after `re-search-forward'. Otherwise, they may return
values corresponding to a different invocation of `re-search-forward'.

TINYCHANGE

:04 04 f3bac3041e71bff7b3c0ca2495bd629d8f3f2833 
634c8baa25f1ad4f3620d9ad26995ac17c26de6b M  lisp

"GNU Emacs 26.3 (build 2, x86_64-pc-linux-gnu, GTK+ Version 3.22.30) of 
2019-09-16"

Org mode version 9.2.6 (release_9.2.6-541-g46767c @ 
/home/thommy/git-emacs/org-mode/lisp/)

Thanks for looking into this.

--
  Thomas



Re: [O] lisp: scoping vars in repetitive defuns

2019-09-17 Thread Nick Dokos
Matt Price  writes:

> I have a number of convenience functions define to help me with grading 
> assignments. As I go through the semester, i update all of these functions 
> modestly so that they'rehelpful for grading the current
> assignment. 
>
> I big chunk of these simple functions is taken up just declaring variables 
> with (let (())) forms.  Each function uses some ofhte same variables, e.g:
>
> (defun dh-find-files ()
>   (interactive)
>   (let* ((base (org-entry-get (point) "ORG_LMS_ASSIGNMENT_DIRECTORY"))
>          (gh (org-entry-get (point) "GITHUB"))
>         (f2o `( ,(concat "Reflection/" gh ".md") ,(concat "students/" gh 
> ".json"  "01/index.html" "02/index.html" "03/style.css" "04/style.css"
>     (message "%s" f2o)
>     ;; make more flexible for resubmits
>     (shell-command (concat "cd " base " && git checkout " gh "-master"))
>     (dolist (x f2o)
>       (if (file-exists-p (concat base "/" x))
>           (find-file-other-window (concat base "/" x) )
>         (message "File %s does not exist, not opening." x)
>
> (defun dh-tests ()
>   (interactive)
>   (let* ((base (org-entry-get (point) "ORG_LMS_ASSIGNMENT_DIRECTORY" ))
>          (gh (org-entry-get (point) "GITHUB")))
>     (with-temp-buffer (shell-command (concat "cd " base " && npm test") t)) 
> ;; the "t" lets us suppress buffer
>     (browse-url-of-file (concat base "/TestResults/testresults.html"))
>     ;; (dh-mocha-run)
>    
>     ))
>
> --
>
> This semester I changed some elements of my workflow and I had to update all 
> the (org-entry-get) calls to new values.  It makes me think the code is less 
> maintainable than it could be.  I would like to do
> something like this:
>
> (lexical-let ((base `(org-entry-get (point) "ORG_LMS_ASSIGNMENT_DIRECTORY")
>    (gh `(org-entry-get (point) "GITHUB")) )
>     (defun dh-find-files ()
> (with-temp-buffer (shell-command (concat "cd " base " && npm test") t)) ;; 
> the "t" lets us suppress buffer
>     (browse-url-of-file (concat base "/TestResults/testresults.html")
>
> Obviously it doesn't work this way. But is there any way to set macros like 
> this to be expanded later inside a function definition? I feel certain there 
> must be...

Are you overthinking this perhaps? Wouldn't variables work? Like e.g.:

(defvar org-lms-assignment-dir-prop "ORG_LMS_ASSIGNMENT_DIRECTORY")

(defun dh-find-files()
  ...
  (let ((base (org-entry-get (point) org-lms-assignment-dir)
  ...

and then you only have one place to change it?

It's quite possible of course that I'm misunderstanding what you are looking 
for.

>
> Thanks,
>
> Matt
>

-- 
Nick

"There are only two hard problems in computer science: cache
invalidation, naming things, and off-by-one errors." -Martin Fowler




Re: [O] lisp: scoping vars in repetitive defuns

2019-09-17 Thread John Kitchin
I don't totally understand what you are trying to do here. If this were
Python, it sounds like you want some kind of class that stores a variable
and reuses it several different functions? Something kind of similar to
that in elisp is a closure, which is like what you described. For example,
here, we define a variable a, and then define two functions that use it
persistently.

#+BEGIN_SRC emacs-lisp
(lexical-let ((a 5))
  (defun f1 (x)
(* a x))

  (defun f2 (x)
(+ a x)))


(list (f1 2) (f2 2))
#+END_SRC

#+RESULTS:
| 10 | 7 |


I think you can wrap this in a macro to make new functions, e.g.

#+BEGIN_SRC emacs-lisp
(defmacro f-maker (a)
  `(lexical-let ((a ,a))
 (defun f1 (x)
   (* a x))

 (defun f2 (x)
   (+ a x

(f-maker 3)

(list (f1 2) (f2 2))
#+END_SRC

#+RESULTS:
| 6 | 5 |


There is also a class system you can probably use like this called eieio,
Here is one approach to doing this.

#+BEGIN_SRC emacs-lisp
(require 'eieio)

(defclass Grade ()
  ((:a :initarg :a)))

(cl-defmethod gf1 ((g Grade) x)
  (* (oref g :a) x))

(cl-defmethod gf2 ((g Grade) x)
  (+ (oref g :a) x))

(let ((G (Grade :a 3)))
  (list (gf1 G 2) (gf2 G 2)))
#+END_SRC

#+RESULTS:
| 6 | 5 |


Finally, maybe the simplest thing to do is pass this information in as an
argument, e.g. a plist or alist, or get them from a function that you only
change in one place?

John

---
Professor John Kitchin
Doherty Hall A207F
Department of Chemical Engineering
Carnegie Mellon University
Pittsburgh, PA 15213
412-268-7803
@johnkitchin
http://kitchingroup.cheme.cmu.edu



On Tue, Sep 17, 2019 at 7:31 AM Matt Price  wrote:

> I have a number of convenience functions define to help me with grading
> assignments. As I go through the semester, i update all of these functions
> modestly so that they'rehelpful for grading the current assignment.
>
> I big chunk of these simple functions is taken up just declaring variables
> with (let (())) forms.  Each function uses some ofhte same variables, e.g:
>
> (defun dh-find-files ()
>   (interactive)
>   (let* ((base (org-entry-get (point) "ORG_LMS_ASSIGNMENT_DIRECTORY"))
>  (gh (org-entry-get (point) "GITHUB"))
> (f2o `( ,(concat "Reflection/" gh ".md") ,(concat "students/" gh
> ".json"  "01/index.html" "02/index.html" "03/style.css"
> "04/style.css"
> (message "%s" f2o)
> ;; make more flexible for resubmits
> (shell-command (concat "cd " base " && git checkout " gh "-master"))
> (dolist (x f2o)
>   (if (file-exists-p (concat base "/" x))
>   (find-file-other-window (concat base "/" x) )
> (message "File %s does not exist, not opening." x)
>
> (defun dh-tests ()
>   (interactive)
>   (let* ((base (org-entry-get (point) "ORG_LMS_ASSIGNMENT_DIRECTORY" ))
>  (gh (org-entry-get (point) "GITHUB")))
> (with-temp-buffer (shell-command (concat "cd " base " && npm test")
> t)) ;; the "t" lets us suppress buffer
> (browse-url-of-file (concat base "/TestResults/testresults.html"))
> ;; (dh-mocha-run)
>
> ))
>
> --
>
> This semester I changed some elements of my workflow and I had to update
> all the (org-entry-get) calls to new values.  It makes me think the code is
> less maintainable than it could be.  I would like to do something like this:
>
> (lexical-let ((base `(org-entry-get (point) "ORG_LMS_ASSIGNMENT_DIRECTORY")
>(gh `(org-entry-get (point) "GITHUB")) )
> (defun dh-find-files ()
> (with-temp-buffer (shell-command (concat "cd " base " && npm test") t)) ;;
> the "t" lets us suppress buffer
> (browse-url-of-file (concat base "/TestResults/testresults.html")
>
>
> Obviously it doesn't work this way. But is there any way to set macros
> like this to be expanded later inside a function definition? I feel certain
> there must be...
>
> Thanks,
>
> Matt
>


[O] lisp: scoping vars in repetitive defuns

2019-09-17 Thread Matt Price
I have a number of convenience functions define to help me with grading
assignments. As I go through the semester, i update all of these functions
modestly so that they'rehelpful for grading the current assignment.

I big chunk of these simple functions is taken up just declaring variables
with (let (())) forms.  Each function uses some ofhte same variables, e.g:

(defun dh-find-files ()
  (interactive)
  (let* ((base (org-entry-get (point) "ORG_LMS_ASSIGNMENT_DIRECTORY"))
 (gh (org-entry-get (point) "GITHUB"))
(f2o `( ,(concat "Reflection/" gh ".md") ,(concat "students/" gh
".json"  "01/index.html" "02/index.html" "03/style.css"
"04/style.css"
(message "%s" f2o)
;; make more flexible for resubmits
(shell-command (concat "cd " base " && git checkout " gh "-master"))
(dolist (x f2o)
  (if (file-exists-p (concat base "/" x))
  (find-file-other-window (concat base "/" x) )
(message "File %s does not exist, not opening." x)

(defun dh-tests ()
  (interactive)
  (let* ((base (org-entry-get (point) "ORG_LMS_ASSIGNMENT_DIRECTORY" ))
 (gh (org-entry-get (point) "GITHUB")))
(with-temp-buffer (shell-command (concat "cd " base " && npm test") t))
;; the "t" lets us suppress buffer
(browse-url-of-file (concat base "/TestResults/testresults.html"))
;; (dh-mocha-run)

))

--

This semester I changed some elements of my workflow and I had to update
all the (org-entry-get) calls to new values.  It makes me think the code is
less maintainable than it could be.  I would like to do something like this:

(lexical-let ((base `(org-entry-get (point) "ORG_LMS_ASSIGNMENT_DIRECTORY")
   (gh `(org-entry-get (point) "GITHUB")) )
(defun dh-find-files ()
(with-temp-buffer (shell-command (concat "cd " base " && npm test") t)) ;;
the "t" lets us suppress buffer
(browse-url-of-file (concat base "/TestResults/testresults.html")


Obviously it doesn't work this way. But is there any way to set macros like
this to be expanded later inside a function definition? I feel certain
there must be...

Thanks,

Matt


Re: [O] Import CSV file, remove columns, print table

2019-09-17 Thread Loris Bennett
Hi John,

Thanks, that's great.  

To get horizontal lines between each participant so that there is a nice
box for the signatures I tried

  return tabulate.tabulate(sorted_results, tablefmt='grid')

This works, but then the 

  #+ATTR_LaTeX: :environment longtable :align |r|l|l|p{8cm}|

seems to be ignored.

Is it possible to tweak the output for 'orgtbl' to insert hlines?

The other solution of course would be to not use 'tabulate' but generate
the table explicitly.

Cheers,

Loris


John Kitchin  writes:

> Here is another 'source block' solution, this time in python. You
> could so something similar in elisp. Here I use the library of babel
> approach so you can call it wherever you want.
>
> #+name: csv
> | ID | Name | Titel / Title | Vorname / First Name | Nachname / 
> Surname | Institution   |
> |  3 | Carol Carrot | Prof. | Carol| Carrot   
>   | University of Veg |
> |  1 | Alice Apple  | Fr./Ms.   | Alice| Apple
>   | Universität zum Apfel |
> |  2 | Bob Birne| Hr./Mr.   | Bob  | Birne
>   | Pear University   |
>
> See https://orgmode.org/worg/org-contrib/babel/library-of-babel.html
>
> #+name: signature-table
> #+BEGIN_SRC python  :var data=csv :results value raw
> results = [[surname, firstname, ""] for _, _, _, firstname, surname, _ in 
> data[1:]]
>
> sorted_results = sorted(results,key=lambda row: row[1])
>
> sorted_results = [[i + 1] + result for i, result in enumerate(sorted_results)]
>
> import tabulate
> return tabulate.tabulate(sorted_results, ['#', 'Surname', 'First name', 
> 'Signature'], tablefmt='orgtbl')
> #+END_SRC
>
> #+call: signature-table(data=csv)
>
> #+RESULTS:
> | # | Surname | First name | Signature |
> |---+-++---|
> | 1 | Apple   | Alice  |   |
> | 2 | Birne   | Bob|   |
> | 3 | Carrot  | Carol  |   |
>
> ---
> Professor John Kitchin 
> Doherty Hall A207F
> Department of Chemical Engineering
> Carnegie Mellon University
> Pittsburgh, PA 15213
> 412-268-7803
> @johnkitchin
> http://kitchingroup.cheme.cmu.edu
>
> On Mon, Sep 16, 2019 at 8:48 AM Loris Bennett  
> wrote:
>
>  Hi John,
>
>  Thanks - that's a nicely compact solution, albeit in the category
>  'source block' and in a language I'm not very skilled at :-)
>
>  I realise that I have slightly misstated the problem.  The ID in the
>  imported CSV is just a key from the database - I don't need it on the
>  list of participants.  However, it would be nice to number the
>  participants, who are sorted by surname.
>
>  How would I insert a column which just numbers the row?
>
>  Cheers,
>
>  Loris
>
>  John Kitchin  writes:
>
>  > You can do something like this:
>  >
>  > #+name: csv
>  > | ID | Name | Titel / Title | Vorname / First Name | Nachname / 
> Surname | Institution   |
>  > |  1 | Alice Apple  | Fr./Ms.   | Alice| Apple 
>  | Universität zum Apfel |
>  > |  2 | Bob Birne| Hr./Mr.   | Bob  | Birne 
>  | Pear University   |
>  > |  3 | Carol Carrot | Prof. | Carol| Carrot
>  | University of Veg |
>  >
>  > #+BEGIN_SRC emacs-lisp :var data=csv
>  > (let ((table (mapcar (lambda (row) (list (nth 0 row) (nth 4 row) (nth 3 
> row))) data)))
>  >   (setf (car table) (append (car table) '("Signature")))
>  >   table) 
>  > #+END_SRC
>  >
>  > #+RESULTS:
>  > | ID | Nachname / Surname | Vorname / First Name | Signature |
>  > |  1 | Apple  | Alice|   |
>  > |  2 | Birne  | Bob  |   |
>  > |  3 | Carrot | Carol|   |
>  >
>  > John
>  >
>  > ---
>  > Professor John Kitchin 
>  > Doherty Hall A207F
>  > Department of Chemical Engineering
>  > Carnegie Mellon University
>  > Pittsburgh, PA 15213
>  > 412-268-7803
>  > @johnkitchin
>  > http://kitchingroup.cheme.cmu.edu
>  >
>  > On Fri, Sep 13, 2019 at 9:36 AM Loris Bennett  
> wrote:
>  >
>  >  Hi,
>  >
>  >  I want to create a list of participants of an event which people can
>  >  sign, so that I can record who actually turned up.
>  >
>  >  From the registration website I can download a CSV file and import it
>  >  into and org file:
>  >
>  >  | ID | Name | Titel / Title | Vorname / First Name | Nachname / 
> Surname | Institution   |
>  >  |  1 | Alice Apple  | Fr./Ms.   | Alice| Apple
>   | Universität zum Apfel |
>  >  |  2 | Bob Birne| Hr./Mr.   | Bob  | Birne
>   | Pear University   |
>  >  |  3 | Carol Carrot | Prof. | Carol| Carrot   
>   | University of Veg |
>  >
>  >  I would like to reduce this to
>  >
>  >  | ID | Nachname / Surname | Vorname /