; muse-orgD0.el (half-baken) ; Esto es un exportador muse->org escrito desde 0 (en contraposición a extendiendo/adaptando el de HTML de Muse) ; This is a muse to org exporter, written from scratch as a Muse exporter. (It is a Muse exporter, just like Muse's HTML exporter, but it outputs org syntax). ; ; Daniel Clemente. dcl441-bugs@yahoo.com. http://www.danielclemente.com/ ; v0.0.1. Started 21.m11.2008, updated until 22.m4.2010 and temporarily abandoned ; What can you expect from this code: ; ; Works: ; - #+TITLE:, #+AUTHOR are correctly set ; - comments are translated from ; to # ; - *italics* → /italics/ and **bold** → *bold* correctly transformed without conflicts. Even ***bold+italics*** → */bold+italics*/ ; - links: ; - implicit links: [[page]] translated to [[file:page.org][page.org]] ; - explicit links: [[like][this]] translated to [[file:like.org][this]] ; - tables: muse tables are transformed to nice org-mode tables. Headers (||), fields (|) and footers (|||) are respected ; - horizontal lines: ----- ; Doesn't work: ; - unordered lists. I got them more or less working except for some bugs which were the cause for me temporarily abandoning this project… ; - ordered lists. I gave sequential order to each item (1., 2., 2.1, 2.2, 2.3, …), but again, there remain the same bugs as with ul ; - definition lists ; - table.el style tables ; - images: not much tested, but should be easy. Caption is adapted ; - ,,…: I didn't even test them ; Expect to find too many debug messages and unintelligible messages and annotations. They need to be cleared. ; To start testing: eval the last function in this file (global-set-key…). It maps key F1 to a test exportation. You will need to provide some .muse file and change the output directory. Find some test files in this directory: sintaxis.muse (very complete), lista.muse ; You may also need package nukneval from Internet. ; Why I don't work on this anymore (23.m4.2010): ; 1) I don't know how list exportation in Muse works, and there's little documentation. ; 2) I don't think it's worth the effort of so many hours I have invested in this. ; 3) I needed the Org version of my Muse files so badly that I finally converted them manually; and that's the procedure I recommend! Forcing them through a muse→org exporter would need anyway that my files had the correct Muse syntax, which wasn't either the case. ; Legal stuff (because this was based or Muse code): ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published ;; by the Free Software Foundation; either version 3, or (at your ;; option) any later version. ;; This program is distributed in the hope that it will be useful, but ;; WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;; General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ; Here starts the program; ¡aquí empieza el programa! ; What do I mean with FARU/IS/BONUS/MALFAR/ATENDAS: see http://www.danielclemente.com/hacer/org.html ; mi prioridad: ;; FARU: ver si tengo que adaptar algo a muse 3.20, que salió hace poco y es el último de Michael Wolson ;; IS: exportar comentarios de muse (empiezan por ;) ;; IS: cambiar la extensión .muse a .org de los ficheros enlazados ;; IS: añadir .org cuando no hay extensión (ej: [[HomePage]]) ;; FARU: no poner siempre descripción ([[a.org][a.org]]), sino sólo [[a.org]]. Tengo que crear expresión nueva ;; IS: enlaces con descripción, ej. [[like][this]] se exportaa como →→file:like.org, deberíaa ser [[file:like((destino)][this]]. Es de tipo link (y creo que ha de serlo, esta pues bien), y no tiene que ver (creo) con lo de link-and-anchor pues no tiene ancla. ;; IS algo como [[con espacios.txt]] no sale enlazado ;; IS: se están buscando/reemplazando signos #+ que fueron introducidos por mí como traducción de otros (#+BEGIN_VERSE…). O escribirlos protegidos o conseguir que anchor se los salte ;; IS: La cita (BEGIN_QUOTE) coge más líneas de las que toca (una cabecera no la corta). Ver justo antes de „Incluído en cliente“ en „Base de datos.muse“. El problema es que (muse-forward-paragraph) ya salta demasiado. He de descubrir qué hacer para que no salte. ;; IS: sublistas: se meten líneas en blanco donde no toca ;; FARU sublistas ordenadas: hay algún número descontrolado (1…4) ;; FARU: sublistas: parece que falla alguna indentación; ver openTrends.muse ;; FARU: dejar igual todo lo que sea posible: ------ ;; IS: tablas ;; FARU: no entender como tablas cosas que no lo son ;; FARU: ciertos tipos de tabla (table.el) no van ;; IS: se pierden letras extrañamente: ;; -Esto es un ejemplo de la sintaxis que se puede usar en Muse, un modo para Emacs. ;; +Esto es un ejemplo de intaxis que se puede usan Muse, un modo para Emacs. ;; Viene por usar mi muse-orgD0-markup-link. Esto es suficiente para reproducirlo: Lleva a mwolson.org: [[http://mwolson.org/][/static/logos/site-logo.png]] ; Extras: ;; BONUS: conversor para ficheros .org ya existentes que busque enlaces *hacia* .muse y los cambie por la versión nueva hacia el .org correspondiente ;; BONUS: sistema para convertir un directorio entero ; para hacer al final: ;; FARU: arreglar los defcustom: ponerles tipo y grupo ; notas: ; 1. la exportación no va si los ficheros forman parte de un proyecto Muse, pues entonces los enlaces salen mal (pone .html.org por ejemplo). ; Esto es debido a muse-publish-link-page que hace explícitamente eso no sé por qué. ; 2. Antes de exportar, exporta a HTML para asegurarte de que tu código Muse hace lo que quieres. Muse a veces pone más tablas o citas de las deseadas; tendrás que corregirlas antes de convertir a Org (defcustom muse-orgD0-extension ".org" "Default file extension for publishing Org-mode files." :type 'string :group 'muse-orgD0 ) (defcustom muse-orgD0-header " (let ( (título (muse-publishing-directive \"title\")) (autor (muse-publishing-directive \"author\")) (fecha (muse-publishing-directive \"date\")) (descripción (muse-publishing-directive \"desc\")) ) (if título (insert \"#+TITLE: \" título \"\n\") ) (if autor (insert \"#+AUTHOR: \" autor \"\n\") ) (if fecha (insert \"#+DATE: \" fecha \"\n\") ) (if descripción (insert \"#+TEXT: \" descripción \"\n\") ) ) " ; FARU: algo mejor que TEXT "Header used for publishing Org files." :type 'string :group 'muse-orgD0) (defcustom muse-orgD0-footer "\n# Página exportada con muse-orgD0.el\n" "Footer used for publishing Org files." :type 'string :group 'muse-orgD0) (defcustom muse-orgD0-markup-regexps ;;;; ;;;; ; FARU: no entiendo todo esto ni sé si es necesario. Por mí, no ;;;; `(;; Beginning of doc, end of doc, or plain paragraph separator ;;;; (10000 ,(concat "\\(\\(\n\\(?:[" muse-regexp-blank "]*\n\\)*" ;;;; "\\([" muse-regexp-blank "]*\n\\)\\)" ;;;; "\\|\\`\\s-*\\|\\s-*\\'\\)") ;;;; ;; this is somewhat repetitive because we only require the ;;;; ;; line just before the paragraph beginning to be not ;;;; ;; read-only ;;;; 3 muse-orgD0-markup-paragraph)) ;;;; ;;;; nil "Cosas raras List of markup rules for publishing a Muse page to HTML. For more on the structure of this list, see `muse-publish-markup-regexps'." :type '(repeat (choice (list :tag "Markup rule" integer (choice regexp symbol) integer (choice string function symbol)) function)) :group 'muse-html) (defcustom muse-orgD0-markup-functions '( ;borrar: (comment . muse-orgD0-markup-comment) (anchor . muse-orgD0-markup-anchor) (table . muse-orgD0-markup-table) (footnote . muse-orgD0-markup-footnote) ; lo añado yo a mano: link url heading list (link . muse-orgD0-markup-link) ; FARU: carcome las palabras (url . muse-orgD0-markup-url) (heading . muse-orgD0-markup-heading) (list . muse-orgD0-markup-list) (quote . muse-orgD0-markup-quote) ) "An alist of style types to custom functions for that kind of text. For more on the structure of this list, see `muse-publish-markup-functions'." :type '(alist :key-type symbol :value-type function) :group 'muse-orgD0) (defcustom muse-orgD0-markup-strings ; FARU: aquí hay mucha materia textual, suficiente para pasar un buen rato convirtiendo '((image-with-desc . "\n#+CAPTION: %3%\n[[file:%1%.%2%]]") ; FARU: probando los tipos de enlace. Ha de ser todo [[]] ; FARU: comprobar que uso el mismo número de %s que el original (image . "[[fiIMAGEle:%s.%s]]") (image-link . "((%s)(file:%s.%s))") (anchor-ref . "{{%s}{%s}}") (url . "%s") ;dclemente. Aquí es donde cambio .muse→.org. Para probar: (link . "[[file:%s.orgĈre]]"). ;debería haber dos %s, el original de HTML está así ; (link . "→→file:%s.org") ; no hace falta añadir el .org, pues la URL ya estará transformada con s/.muse$/org/ ; (link . "→→[[file:%s.org][%s]]") (link . "[[file:%s][%s]]") ; FARU: ahora no va el mostrar texto distinto (link-and-anchor . "««%s.org#%s»«%s»") (email-addr . "[[mailto:%s][%s]]") (anchor . "ANCLA<<%s>>FINANCLA") (emdash . "--") ; FARU ; (comment-begin . "\n#+BEGIN_COMENT\n") ; (comment-end . "\n#+END_COMMENT\n") ; ¿bloques o normal? (comment-begin . "# ") (comment-end . "") (rule . "-----") (fn-sep . "-----\n") (no-break-space . " ") ; FARU (enddots . "....") (dots . "...") ; (section . "* ") ; We don't use these because we don't change **** markup at all ; (section-end . "") ; (subsection . "** ") ; (subsection-end . "") ; (subsubsection . "*** ") ; (subsubsection-end . "") ; (section-other . "**** ") ; (section-other-end . "") (begin-underline . "_") (end-underline . "_") (begin-literal . "~") (end-literal . "~") (begin-cite . "\n#+BEGIN_QUOTE(decita)\n") (begin-cite-author . "") ; FARU (begin-cite-year . "") ; FARU (end-cite . "\n#+END_QUOTE\n") (begin-emph . "/") (end-emph . "/") (begin-more-emph . "*") (end-more-emph . "*") (begin-most-emph . "*/") (end-most-emph . "/*") (begin-verse . "\n#+BEGIN_VERSE\n") (verse-space . "  ") (end-verse-line . "Ĵ\n") (end-last-stanza-line . "Ĝ\n") (empty-verse-line . "Ĉ\n") (end-verse . "\n#+END_VERSE\n") (begin-example . "\n#+BEGIN_EXAMPLE\n") (end-example . "\n#+END_EXAMPLE\n") (begin-center . "\n#+BEGIN_CENTER\n") ; Está desde 6.25 (end-center . "\n#+END_CENTER\n") ; Está desde 6.25 (begin-quote . "\n#+BEGIN_QUOTE\n") (end-quote . "\n#+END_QUOTE\n") ; (begin-quote-item . "") ; not needed ; (end-quote-item . "") ; not needed (begin-uli . "") (end-uli . "") (begin-uli-item . "- ") ; esto debería ser innecesario pues puedo simplemente quitar la indentación de 1 espacio inicial y dejar el estilo Muse (end-uli-item . "") (begin-oli . "") (end-oli . "") (begin-oli-item . "%1%. ") (end-oli-item . "") (begin-dl . "") (end-dl . "") (begin-ddt . "- ") (end-ddt . " :: ") (begin-dde . "") ; (end-dde . "¿dd que empiezan en la siguiente ") ; FARU: verqués (end-dde . "") ) "Strings used for marking up text as HTML... o orgD0. These cover the most basic kinds of markup, the handling of which differs little between the various styles." :type '(alist :key-type symbol :value-type string) :group 'muse-orgD0) (defcustom muse-orgD0-markup-tags '(("class" t t t muse-orgD0-class-tag) ("src" t t nil muse-orgD0-src-tag)) "A list of tag specifications, for specially marking up HTML." :type '(repeat (list (string :tag "Markup tag") (boolean :tag "Expect closing tag" :value t) (boolean :tag "Parse attributes" :value nil) (boolean :tag "Nestable" :value nil) function)) :group 'muse-orgD0) (defcustom muse-orgD0-style-sheet " #+STYLE: " "Store your stylesheet definitions here." :type 'string :group 'muse-orgD0) (muse-define-style "orgD0" :suffix 'muse-orgD0-extension ; IS, probar :regexps 'muse-orgD0-markup-regexps ; IS, probar :functions 'muse-orgD0-markup-functions ; IS, probar :strings 'muse-orgD0-markup-strings ; IS, probar :tags 'muse-orgD0-markup-tags ; IS, probar :specials 'muse-orgD0-decide-specials ; IS, probar :before 'muse-orgD0-prepare-buffer ; IS, probar :before-end 'muse-orgD0-munge-buffer ; IS, probar :after 'muse-orgD0-finalize-buffer ; IS, probar :header 'muse-orgD0-header ; IS, probar :footer 'muse-orgD0-footer ; IS, probar :style-sheet 'muse-orgD0-style-sheet ; IS, probar :browser 'muse-orgD0-browse-file) ; IS, probar (defun muse-orgD0-browse-file (file) (find-file file)) (defun muse-orgD0-finalize-buffer () ; pues de momento nada; expHTML cambia la codificación ) (defun muse-orgD0-prepare-buffer () ; nada ; FARU: ¿quizás aquí hay que exportar comentarios? ; FARU: no sé el sitio bueno para establecer mis variables (setq muse-publish-comments-p t) ) (defun muse-orgD0-munge-buffer () ; para hacer al final ; nada ) (defun muse-orgD0-markup-paragraph () ; nada pues los párrafos de org son iguales que los de muse ) (defun muse-orgD0-markup-comment () ;(debug) ;(beginning-of-line) (delete-char 1) (muse-insert-markup "#") ; FARU: borrar pues lo solucioné con lo que provee Muse (ignore '( (goto-char (match-end 0)) (beginning-of-line) (delete-char 1) (muse-insert-markup "#") (muse-insert-markup (muse-markup-text 'comment-end)) (muse-publish-mark-read-only (match-beginning 1) (match-end 1)) ; FARU: no hago nada porque los quiero... aunque con # ;(ignore '( ; (if (null muse-publish-comments-p) ; "" (goto-char (match-end 0)) (muse-insert-markup (muse-markup-text 'comment-end)) (if (match-beginning 1) (progn (muse-publish-mark-read-only (match-beginning 1) (match-end 1)) (delete-region (match-beginning 0) (match-beginning 1))) (delete-region (match-beginning 0) (match-end 0))) (goto-char (match-beginning 0)) (muse-insert-markup (muse-markup-text 'comment-begin)) )) ) ;) ; Muse documentation: ; If you begin a line with "#anchor" – where "anchor" can be any word that doesn't contain whitespace – it defines an anchor at that point into the document. This point can be referenced using "page#anchor" as the target in a Muse link. (defun muse-orgD0-insert-anchor (anchor) ; FARU: esto no está adaptado a orgD0 y va a seguir comportándose como HTML. Cambiar "Insert an anchor, either around the word at point, or within a tag." (muse-insert-markup "←prU←") (skip-chars-forward (concat muse-regexp-blank "\n")) (if (looking-at (concat "<\\([^" muse-regexp-blank "/>\n]+\\)>")) (let ((tag (match-string 1))) (goto-char (match-end 0)) (muse-insert-markup (muse-markup-text 'anchor anchor)) (when muse-html-anchor-on-word (or (and (search-forward (format "" tag) (muse-line-end-position) t) (goto-char (match-beginning 0))) (forward-word 1))) (muse-insert-markup "")) (muse-insert-markup (muse-markup-text 'anchor anchor)) (when muse-html-anchor-on-word (forward-word 1)) (muse-insert-markup "\n"))) (defun muse-orgD0-markup-anchor () (unless (or (get-text-property (match-end 1) 'muse-link) ; #+BEGIN_VERSE, #+END_SRC etc. aren't really markers but Org-commands we wrote ourselves. So we ignore all markers starting with + ; TODO: maybe they shouldn't be /detected/ as anchors in the first place (= ?+ (elt (match-string 2) 0)) ) (save-match-data (muse-orgD0-insert-anchor (match-string 2))) (match-string 1))) (defun muse-orgD0-markup-table (&optional attributes) "Publish the matched region into a table. If a string ATTRIBUTES is given, pass it to the markup string begin-table." (let* ((table-info (muse-publish-table-fields (match-beginning 0) (match-end 0))) (row-len (car table-info)) (supports-group (not (string= (muse-markup-text 'begin-table-group row-len) ""))) (field-list (muse-orgD0-sort-table (cdr table-info))) ; last-part column-max-lengths línea-barras) (if ; validations (and table-info ; sometimes it's nil ; There's a validation I would like to do but I can't: ; Muse produces a strange table description for instance with this input: ; Jefe de proyectos ||||| Arquitecto técnico ; This table-info will be obtained: ; (2 (5 "Jefe de proyectos" "Arquitecto técnico")) ; The 5 is there because there were 5 bars, but 5 bars mean nothing to us (neither to Muse -- it will export invalid HTML). ; I wanted to do: 1=body, 2=header, 3=footer, hline, that's the only we accept. If it has more, it isn't a table to us ;; (loop for Row in field-list always (member (nth 0 Row) '(0 1 2 hline))) ; But the table was already deleted by Muse! Therefore the best I can do is accept any number of bars, and if they are >3, treat them as 1 ) (progn ; A partir de: ; (3 (2 "org" "style" "table") (1 "one" "" "one") (1 "two" "two" "") (1 "" "three" "three") (hline) (1 "more" "stuff" "")) ; sacar la longitud máxima de los textos de cada columna; ej: (4, 5, 5) ; Prueba, para simplificar: ;(column-max-lengths (make-list row-len 10)) ; ; Probando: ; (setq TodosValores (cdr '(3 (2 "org" "style" "table") (1 "one" "" "one") (1 "two" "two" "") (1 "" "three" "three") (hline) (1 "more" "stuff" "")))) ; bien; 50%: (loop for x in TodosValores if (member (nth 0 x) '(2 1 3)) collect (length (nth 1 x))) ; mejor: (loop for x in TodosValores if (member (nth 0 x) '(2 1 3)) maximize (length (nth 1 x))) ; FARU: borrar pruebas (setq column-max-lengths (loop for Column from 1 upto row-len collect ; (loop for Row in field-list if (member (nth 0 Row) '(2 1 3)) maximize (length (nth Column Row))) (loop for Row in field-list unless (member (nth 0 Row) '(hline)) maximize (length (nth Column Row))) ) ) ; Línea de barras ; Ej: 4 5 5 da: "|------+-------+-------|" ; Fórmula: ( ("|" si primero, "+" si no)+ "-" + "-"*long + "-" )*cada_campo +"|" (setq línea-barras (concat "|" (substring (apply 'concat ( loop for column-max-length in column-max-lengths collect (concat "+-" (make-string column-max-length ?-) "-")) ) 1) "|\n") ) ;(message "ᚏᚏᚏtengo esta tablaᚏᚏᚏ:") ;(prin1 table-info) ;(message "…………… y además field-list (ordenado -u) es: ") ;(prin1 field-list) ;(message "∩∩∩∩∩ FIN ∩∩∩∩∩∩") ; ejemplo de lo que recibo en table-info: ; (3 (2 "org" "style" "table") (1 "one" "" "one") (1 "two" "two" "") (1 "" "three" "three") (hline) (1 "more" "stuff" "")) ; Pero field-list está ordenado (he cambiado la función de ordenación): ; ((2 "org" "style" "table") (1 "one" "" "one") (1 "two" "two" "") (1 "" "three" "three") (hline) (1 "more" "stuff" "")) ; Plan: ; - empezar pintando líneas normales con | donde toca ; - tras un título, poner |-----| ; - antes de un pie, poner |-----| ; Traducido: ; - crear dos cadenas: barras="|------------|" y la campos="| campo1 | campo2 |" ; - poner (pie→ barras)+campos+(título→ barras) (dolist (fields field-list) (let* ((type (car fields)) (cell-values (cdr fields)) ; A partir de cell-values: ("org" "style" "table"), obtener línea-campos: "| org | style | table |" ; para probar: ; FARU: borrar ;(línea-campos "| bla | bla | bla |\n") ; (setq Valores '("uno" "dos" "tres" "cuatro")) ; (setq TamTextos '(5 4 4 8)) ; mala: ; (loop for x in Valores for y in TamTextos collect (list x y)) ; mejor: ; (apply 'concat (append (loop for x in Valores for y in TamTextos collect (format (concat "| %-" (number-to-string y) "s ") x)) (list "|"))) (línea-campos (apply 'concat (append (loop for cell-value in cell-values for cell-text-max-length in column-max-lengths collect (format (concat "| %-" (number-to-string cell-text-max-length) "s ") cell-value)) (list "|\n"))) ) ) ; combinar cadenas (muse-insert-markup ; type: hline (horizontal line), 1 (body line), 2 (head line), 3 (footer line) (cond ((eq type 'hline) línea-barras) ((member type '(2 1 3)) (concat (if (= type 3) línea-barras) ; 3=footer. Then we need the dashed line above. línea-campos ; for header, footer or body (2 1 3 resp.) we write a line with the fields (if (= type 2) línea-barras) ; 2=header. Then we need the dashed line below. )) ((and (numberp type) (> type 3)) ; I consider this a Muse bug. This happens with lines like aaa||||bb (type=4), which I wouldn't classify as tables. Since a validation is futile (see comments about it above), we accept those inputs as if they were aaa|bb línea-campos ) "" ) ) ) ) (insert ?\n) )) )) (defun muse-orgD0-sort-table (table) "Sort the given table structure so that it contains the header, body and footer rows exactly in that order. The original function did header-footer-body." ;; Note that the decision matrix must have a nil diagonal, or else ;; elements with the same type will be reversed with respect to each ;; other. ;; dclemente: rows are BHF and columns too. The question to ask at each cell is: „¿comes the one at this row earlier than the one in this column?“ (let ((decisions '((nil nil t) ; body: before footer (t nil t) ; header: before everything else (nil nil nil)))) ; footer: not before anything (sort table #'(lambda (l r) (and (integerp (car l)) (integerp (car r)) (nth (1- (car r)) (nth (1- (car l)) decisions))))))) (defun muse-orgD0-markup-footnote () "Footnotes are expressed in the same way in Muse and Org, therefore no conversion is needed." nil ) ; FARU. traducir: ; enlace a página normal: [[mipágina]] → [[file:mipágina.org]] ; sí que se está ejecutando (defun muse-orgD0-markup-link () ;(ignore ' ;(debug) (let (desc explicit orig-link link) (setq explicit (save-match-data (if (string-match muse-explicit-link-regexp (match-string 0)) t nil))) ; aquí, match-beginning0 y match-end0 aún valen bien. explicit:t y las variables valen lo bueno (setq orig-link (if explicit (match-string 1) (match-string 0))) (setq desc (when explicit (match-string 2))) (setq link (if explicit ; FARU: no debería hacer ningún tratamiento para el explícito (el común) ni el otro (muse-handle-explicit-link orig-link) (muse-handle-implicit-link orig-link))) (when (and link (or explicit (not (or (eq (char-before (match-beginning 0)) ?\") (eq (char-after (match-end 0)) ?\"))))) ;; if explicit link has no user-provided description, treat it ;; as if it were an implicit link (when (and explicit (not desc)) (setq explicit nil)) ; FARU: link y orig-link son iguales en todas mis pruebas ;(muse-publish-insert-url "Wissensmanagement" nil "Wissensmanagement" nil) ; FARU: evitar .html.org. No quiero que llame a muse-publish-url porque los enlaces internos no son URLs; no quiero ni el %20 ni el .html al final ; nota: muse-publish-url me da: [[file:openTrends.html.org]] (23.3.2009: sólo si está dentro de un proyecto) (let ((text ; Nota muuuuuuuuuuy importante: muse-orgD0-publish-url tiene el efecto secundario de hacer string-match y por tanto luego causa una carcoma en el texto muy fea y que me cuesta mucho resolver. Por eso hay que usar save-match-data (save-match-data (muse-orgD0-publish-url link desc orig-link explicit) ) )) (message "voy a hacer insert-url con link{%s} desc{%s} orig-link{%s} explicit{%s} →→→ muse-orgD0-publish-url me da: %s" link desc orig-link explicit text) ; dclemente: no toca aquí cambiar extensión .muse→.org, sino en la expreg. de arriba ;(if link (setq link (concat link ".orgĈml"))) ;(message "pero mejor lo haré con %s %s %s %s" link desc orig-link explicit) ; FARU: encontrar la diferencia entre muse-orgD0-publish-url y muse-orgD0-insert-url. ¿No se podría estar sólo rcon una de ellas? Es seguro que la primera me carcome ; la carcoma no es por mi función pues si llamo a la otra, también pasa (muse-orgD0-insert-url link desc orig-link explicit) ;(muse-publish-insert-url link desc orig-link explicit) ) ) ) ) ; copia de muse-publish-insert-url pero llamando a mi función (defun muse-orgD0-insert-url (url &optional desc orig-url explicit) "Resolve a URL into its final form." ; IS: estos match-beginning y match-end eran laa causa de la carcoma del texto (delete-region (match-beginning 0) (match-end 0)) ;(debug) ; El mensaje inferior me dice: De inicio 23 a fin 27 tengo: la s, para url http://mwolson.org/ ; IS: hay algo que cambia match-beginning y match-end antes de llegar aquí… ;;;;(message "De inicio %d a fin %d tengo: %s, para url %s" (match-beginning 0) (match-end 0) (buffer-substring (match-beginning 0) (match-end 0)) url) ;;;;(muse-insert-markup (concat "»" ;(substring ;;;; (delete-and-extract-region (match-beginning 0) (match-end 0)) ;1 -1) ;;;;"«") ;;;; ;(muse-insert-markup "∴") ;(goto-char (match-end 0)) (muse-insert-markup "←") ;(goto-char (match-beginning 0)) (muse-insert-markup "→") (let ((text (muse-orgD0-publish-url url desc orig-url explicit))) (when text (muse-insert-markup text)))) ; copia de muse-publish-url (defun muse-orgD0-publish-url (url &optional desc orig-url explicit) "Resolve a URL into its final form. NOOOOOOOTA: va a destrozar match-data y va a causar una carcoma importante en próximo código que use match-beginning etc. Así que usa save-match-data SIEMPRE aquí. Diría que además claramente escribe cosas en el búfer. " (let ((unesc-url url) (unesc-orig-url orig-url) (unesc-desc desc) type anchor) ;; Transform URL ; (dolist (transform muse-publish-url-transforms) (dolist (transform muse-orgD0-url-transforms) (setq url (save-match-data (when url (funcall transform url explicit))))) ; aquí ya se se ha transformado .muse→.org gracias a muse-orgD0-url-transforms ; también se ha añadido .org. Ej: [[hola]] hay traducido a [[hola.org][hola]], pero con cuidado, pues [[/n/hola]] ha de quedar igual ;; Classify URL (let ((target (muse-publish-classify-url url))) (setq type (car target) ; ¡no te escapes! url (cadr target) anchor (cddr target) ; url (if (eq type 'image) ; (muse-publish-escape-specials-in-string (cadr target) ; 'image) ; (muse-publish-escape-specials-in-string (cadr target) 'url)) ; anchor (muse-publish-escape-specials-in-string ; (cddr target) 'url))) )) ;; Transform description (if desc (setq desc (muse-orgD0-publish-url-desc desc explicit)) (when orig-url (setq orig-url (muse-orgD0-publish-url-desc orig-url explicit)))) (message "tipo %s, desc %s, orig-url %s, unesc-url %s, target %s, url %s, anchor %s" type desc orig-url unesc-url target url anchor) ;; Act on URL classification (cond ((eq type 'anchor-ref) (muse-markup-text 'anchor-ref anchor (or desc orig-url))) ((and unesc-desc (string-match muse-image-regexp unesc-desc)) (let ((ext (or (file-name-extension desc) ""))) ; no te escapes ;(setq desc (muse-publish-escape-specials-in-string unesc-desc ; 'image)) (setq desc unesc-desc) (setq desc (muse-path-sans-extension desc)) (muse-markup-text 'image-link url desc ext))) ((string= url "") desc) ((eq type 'image) (let ((ext (or (file-name-extension url) ""))) (setq url (muse-path-sans-extension url)) (if desc (muse-markup-text 'image-with-desc url ext desc) (muse-markup-text 'image url ext)))) ((eq type 'link-and-anchor) (muse-markup-text 'link-and-anchor url anchor (or desc orig-url) (muse-path-sans-extension url))) ((eq type 'link) (muse-markup-text 'link url (or desc orig-url))) (t (or (and (or desc ;; compare the not-escaped versions of url and ;; orig-url (not (string= unesc-url unesc-orig-url))) (let ((text (muse-markup-text 'url-and-desc url (or desc orig-url)))) (and (not (string= text "")) text))) (muse-markup-text 'url url (or desc orig-url))))))) (defvar muse-orgD0-url-transforms '(muse-resolve-url muse-orgD0-change-muse-extension muse-orgD0-add-org-extension-to-wikilinks) "Same as muse-publish-url-transforms but with 2 new ones added.") (defun muse-orgD0-change-muse-extension (url &rest ignored) "Change URLs like a.muse to a.org so that links between Muse pages still work (now between Org pages)" ;(setq url (replace-regexp-in-string ".muse$" muse-orgD0-extension url) ;) ) ; FARU: en la descripción sigue quedando a.muse. Lo que hay que hacer es quitar la descripción (defun muse-orgD0-add-org-extension-to-wikilinks (url &rest ignored) "Change URLs like Test to Test.org to make Muse [[links]] resolve to the correct .org file (links.org). URLs which don't look like single file names remain unchanged: http://something, /etc/blabla etc. (we won't want to return /etc/blabla.org) " (if (string-match "/" url) url (concat url muse-orgD0-extension)) ) (defun muse-orgD0-publish-url-desc (desc explicit) ; No se hará ninguna transformación ; (when desc ; (dolist (transform muse-publish-desc-transforms) ; (setq desc (save-match-data ; (when desc (funcall transform desc explicit))))) ; (setq desc (muse-link-unescape desc)) ; (muse-publish-escape-specials-in-string desc 'url-desc)) desc ) ; igual pero llamando a mi función (defun muse-orgD0-markup-url () (unless (or (eq (char-before (match-beginning 0)) ?\") (eq (char-after (match-end 0)) ?\")) (let ((url (match-string 0))) (muse-orgD0-insert-url url nil url)))) (defun muse-orgD0-class-tag (beg end attrs) ; FARU: traducir, pero no sé qué equivalencia tiene esto en org (let ((name (cdr (assoc "name" attrs)))) (when name (goto-char beg) (muse-insert-markup "") (save-excursion (goto-char end) (muse-insert-markup ""))))) (defun muse-orgD0-src-tag (beg end attrs) "en org es fácil; no hay nada que colorear" (save-excursion (goto-char beg) (muse-insert-markup "\n#+BEGIN_SRC\n") (goto-char end) (muse-insert-markup "\n#+END_SRC\n") ) ) (defun muse-orgD0-decide-specials (contexto) ;"delega" ;(muse-xml-decide-specials contexto) ; No hacer ninguna transformación del estilo < → < pues esto no es XML ) ; Note: differently to muse (which accepts *, ** and ***), we allow any level of heading. We just let it like it is. ; We also don't add extra newlines (defun muse-orgD0-markup-heading () (muse-insert-markup (delete-and-extract-region (match-beginning 0) (match-end 0) )) (forward-line 1) ) ; ; Muse: ; - bullet item one ; - bullet item two ; ; Muse: ; 1. Enum item one ; 2. Enum item two ; ; Muse: ; Term1 :: ; This is a first definition ; And it has two lines; ; no, make that three. ; ; Term2 :: This is a second definition ; ; ; Org: org can handle ul and ol, but treats dl as paragraphs. Just adding a - before, dl works. ;(defun muse-orgD0-markup-list () ;(muse-publish-markup-list) ;) (defun muse-orgD0-markup-list () "Markup a list entry. This function works by marking up items of the same list level and type, respecting the end-of-list property. muse-orgD0: to maintain list items as in the original list, this function adds initial spaces to them. ← FARU: ¿esto está bien? muse-orgD0: remember that Muse list items *must* start with a space, otherwise they aren't lists. " ; FARU: adaptar. De momento sólo trata ul ; FARU #A: la identación no va siempre ;; Ej (borrar luego): ;- - uno ;- - uno1 ;- - uno2 ;- - dos ;- - dos1 ;- -dos11 ;- - dos2 ;- - tres ;+ ;+- uno ;+ ;+ - uno1 ;+ - uno2 ;+- dos ;+ ;+ - dos1 ;+ ;+ - dos11 ;+ - dos2 ;+- tres (let* ((str (match-string 1)) (type (muse-list-item-type str)) ; mi original: ; (indent (buffer-substring (muse-line-beginning-position) ; (match-beginning 1))) ; prueba1: ; (indent (concat "«línea·era:" (buffer-substring (muse-line-beginning-position) (muse-line-end-position)) "»")) ;← esto resulta bien: vea las cadenas tal como esperaba ; prueba2: ; contar número de espacios iniciales de la línea actual, y usar eso. Chaapucero, pero parece que va ; FARU: ¿realmente es tan bueno y va? Parece que va muy bien excepto en 1) la línea inicial, y en 2) la lista del dekdu etc. (ver abajo) (indent (make-string (let ((this-line (buffer-substring (muse-line-beginning-position) (muse-line-end-position)))) (loop for i from 0 to (length this-line) while (char-equal (elt this-line i) ? ) count t)) ? )) ; prueba simplificada: contar número de espacios iniciales; seguro que hay mejores formas… ;(let ((cad " h ola")) (loop for i from 0 to (length cad) while (char-equal (elt cad i) ? ) count t)) (post-indent (length str))) (message "\nTengo «%s», con 1:«%s» e indent:«%s»" (match-string 0) (match-string 1) indent) (message "Y match-data: %s" (match-data t)) (message "Pero la línea real es ésta: «%s»" (buffer-substring (line-beginning-position) (line-end-position))) ; (debug) ; FARU: parece que no coge bien la indentación (toda) ; El problema es en la tercera lista con: Tengo « - », con 1:« - » e indent:« » ; Pues debería decir: Tengo « - » ; Dice también: Pero la línea real es ésta: « - dudekunu (3 spacoj komence)» ; FARU: ¿quién ha cambiado la lista para que esa línea tenga sólo 2 espacios en vez de 3? ; Quizás Muse va transformando las listas de nivel en nivel y restando indentación a todas las sublistas; entonces tendría que ir con cuidado de no insertar la indentación que veo en una sublista, sino ésa más la que ya hay en el búfer temporal de trabajo ; FARU: conseguir ver el fichero temporal que Muse va creando, así lo puedo estudiar en diferentes momentos del exportado ; lo puedo hacer con (switch-to-buffer (current-buffer)) ; ;(debug) ; la expresión regular es (creo): ; (2200 "^[[:blank:]]*\\(\\([^\n[:blank:]].*?\\)?::\\(?:[[:blank:]]+\\|$\\)\\|[[:blank:]]-[[:blank:]]*\\|[[:blank:]][0-9]+\\.[[:blank:]]*\\)" 0 list) ; FARU: parece que el muse-html original ya coge indentación nula; eso no lo quiero. Coger número de espacios inicial ← no sé si esto concuerda con el algoritmo usado (cond ((or (get-text-property (muse-list-item-critical-point) 'read-only) (get-text-property (muse-list-item-critical-point) 'muse-link)) nil) ((eq type 'ul) (unless (eq (char-after (match-end 1)) ?-) (message "Estoy borrando: «%s»" (buffer-substring (match-beginning 0) (match-end 0))) (setq loquehabíaantes (buffer-substring (match-beginning 0) (match-end 0))) ; no es muy útil. FARU: borrar (delete-region (match-beginning 0) (match-end 0)) ; (muse-publish-ensure-blank-line) (muse-insert-markup (muse-markup-text 'begin-uli)) (save-excursion (muse-publish-surround-text (concat ; FARU: estas 2 líneas de prueba no van bien. „indent“ tendría que ser suficiente. Pero tampoco va… FARU: dejar „indent“ "«" loquehabíaantes "»" "[" indent "]" ; (concat indent "…" ; (concat "→" indent "←" (muse-markup-text 'begin-uli-item)) (muse-markup-text 'end-uli-item) (lambda (indent) ; (muse-insert-markup (concat "- «" indent "»")) ; (muse-insert-markup (concat indent)) ; (muse-insert-markup (concat "∴" indent)) (muse-forward-list-item 'ul indent) ) indent post-indent) (muse-insert-markup-end-list (muse-markup-text 'end-uli)) ) (forward-line 1))) ((eq type 'ol) ;(debug) (let ( ; ;(bullet-number (string-to-number (match-string 0))) (bullet-number 1) ; start always on 1 instead of preserving the original ) (delete-region (match-beginning 0) (match-end 0)) (muse-publish-ensure-blank-line) (muse-insert-markup (muse-markup-text 'begin-oli)) (save-excursion (muse-publish-surround-text indent ; beg-tag doesn't contain the bullet because it's dynamic: we write it in the move-func (muse-markup-text 'end-oli-item) (lambda (indent) (muse-insert-markup (muse-markup-text 'begin-oli-item (number-to-string bullet-number))) (setq bullet-number (1+ bullet-number)) ;(message "El contador ha pasado a %s" bullet-number) ; Importante: esta línea va al final pues es la de retorno (muse-forward-list-item 'ol indent) ) indent post-indent) (muse-insert-markup-end-list (muse-markup-text 'end-oli)) ) (forward-line 1))) (t ;(eq type 'dl) (goto-char (match-beginning 0)) (muse-publish-ensure-blank-line) (muse-insert-markup (muse-markup-text 'begin-dl)) (save-excursion (muse-publish-surround-dl indent post-indent) (muse-insert-markup-end-list (muse-markup-text 'end-dl))) ;142857: ; (save-excursion ; (muse-publish-surround-text ; "-ĉ" ; "ñ" ; (lambda (indent) ; (muse-forward-list-item 'dl indent)) ; indent post-indent) ; ) (forward-line 1)))) nil) ; FARU: plantearme el estudiar más muse-publish-surround-text (la original) para hacer un 2º intento una vez comprendido el algoritmo (defun muse-orgD0-markup-quote () "Markup a quoted paragraph. Like muse-publish-markup-quote, but tries to envolve paragraphs correctly even in this case: Some text: This is quoted *** This heading should end the quote. Past the quoted text. If you step on the „This is quoted“ and do a (muse-forward-paragraph), it jumps to „Past the quoted text“ incorrectly. Therefore we need to pass a custom regexp to muse-forward-paragraph which considers headings too. This is the only change in this function. " ; FARU probaaaaaaaaar mucho ; FARU: me encuentro con cosas como: ; ←prU←ANCLA<<+BEGIN_QUOTE>>FINANCLA ; Eso es que #+BEGI… no estaba bien protegido (let* ((ws (match-string 1)) (centered (>= (string-width ws) 6)) (begin-elem (if centered 'begin-center 'begin-quote-item)) (end-elem (if centered 'end-center 'end-quote-item))) (replace-match "" t t nil 1) (unless centered (muse-insert-markup (muse-markup-text 'begin-quote))) (muse-publish-surround-text (muse-markup-text begin-elem) (muse-markup-text end-elem) (function (lambda (indent) ; (muse-forward-paragraph) (muse-forward-paragraph ; The final expression I want is "^\\(*+ .*\\|\\s-*\\(\n\\|\\'\\)\\)", this is the default one plus the *+. muse-forward-paragraph adds more to it, but it our regexp still works… "^\\(*+ .*\\|\\s-*\\(\n\\|\\'\\)\\)" ) nil))) (unless centered (muse-insert-markup (muse-markup-text 'end-quote))))) ; consulta: ;(find-file "~/.emacs.d/muse/lisp/muse-html.el") ;Evalúa; esto hace que F11 cargue el nuevo fichero actual y exporte ; (local-set-key [f11] (lambda nil (interactive) (global-set-key [f1] (lambda nil (interactive) (let ( (fuente "~/proj/ejd/data/wt/pk8q11ohe0/sintaxis.muse") (búfer "sintaxis.org") ; otras pruebas ;(fuente "~/wiki/pruebas.muse") ;(búfer "pruebas.org") ; para la cosa concreta que necesito desarrollar en muse-orgD0 ;(fuente "~/proj/emacs/miniprueba.muse") ;(búfer "miniprueba.org") ;(fuente "~/wiki/Java.muse") ;(búfer "Java.org") ; objetivo importante ;(fuente "~/wiki/openTrends.muse") ;(búfer "openTrends.org") (muse-project-alist nil) ; pues si no pondrá .html.org; no entiendo el porqué (debug-on-error t) ; pues si no me muestra erorres gordos sólo como avisos en "*Warnings*" ) (with-current-buffer "muse-orgD0.el" (nuke-and-eval)) (muse-publish-file fuente "orgD0" "/n/" t) ; marcar como ¬modificado si hace falta, y luego cerrar (if (get-buffer búfer) (with-current-buffer búfer (set-buffer-modified-p nil) (kill-this-buffer)) ) ; no siempre necesito el origen y destino; sólo la diferencia ;(find-file fuente) ;(find-file (concat "/n/" búfer)) (diff fuente (concat "/n/" búfer)) ; Ej: (diff "/home/dc/proj/ejd/data/wt/pk8q11ohe0/sintaxis.muse" "/n/sintaxis.org") ; Nota: no es que no vaya, es que ahora he de usar F1, no F11 ;conicicles: (icicle-select-window-by-name "*Diff*") (select-window (get-buffer-window "*Diff*")) )) )