Skip to content

Twenty Thousand Leagues under the Sea by Jules Verne

License

Notifications You must be signed in to change notification settings

mlao-pdx/twenty-thousand

Repository files navigation

Caution

Unless you want to donate your writing to the public domain, make sure you replace the LICENSE file with one that reflects your intent.

Do not forget to empty out .asciidoctorconfig.adoc and to press option+a. From there on in, follow the snippet’s guidance.

Note

This repository merely documents my configuration and makes it a template. I share it here, mostly because I want to acknowledge the folks whose tools I use.

Lozenge adheres to semantic versioning.

Lozenge v0.5.0: A tool set configuration for writing fiction.

If these sentiments ring true:

  • formatting only gets in the way;

  • flat files rule;

  • detailed version control is a savior;

  • navigation should be simple;

  • scope and continuity are a pain to keep straight;

  • semantic line breaks are useful;

  • online is good, but offline is a must;

then this configuration might be for you.

Introduction

This is a template repository set up for writing fiction in AsciiDoc using Visual Studio Code, some of its extensions, Pandoc, and Word.

This set-up was created for MacOS and might work out-of-the-box for Linux flavors. For Windows machines tweaking will be required, especially the convertAsciiDocToDocx macro defined in .vscode/settings.json.

Lozenge’s minimalistic approach means that if you explore the snippets (option+s) and the Keybindings, you already know how most of Lozenge works.

Lozenge leans heavily on AsciiDoc attributes and macros, making it a good idea to read up on AsciiDoc syntax.

A few concepts cannot be found in the snippets and AsciiDoc syntax:

  1. Files and document types are Lozenge’s building blocks:

    1. the Explorer manages your files and folders, however deep or shallow you want

    2. ToDo Tree navigates your writing, however deep or shallow it is stored

  2. Word document heading styles assume the use of = Parts in your book

  3. PDF and DOCX files stored in (sub)folders not called assets/ or published/ are deemed generated and will not be versioned.

Installation

These applications need to be installed:

  1. Git for version control;

    1. if storing large, or many, binary files, install GitLFS;

  2. Visual Studio Code. Allow it to manage your Github repository;

  3. extensions per the workspace recommendations;

    1. AnelGroup.word-stats: Detailed stats on word distributions

    2. arturodent.find-and-transform: Automate content changes

    3. asciidoctor.asciidoctor-vscode: Main support for writing asciidoc

    4. ban.spellright: A void, Miss Steaks, née Tiff Lee

    5. eamodio.gitlens: Search and visualize our changes over time, publication tags

    6. edonet.vscode-command-runner: Turn Terminal commands into vscode commands

    7. geddski.macros: Turn multiple vscode commands into one

    8. Gruntfuggly.todo-tree: Navigate to todos and tags

    9. hoovercj.vscode-settings-cycler: JSON schema issue and Zen toggle

    10. kirozen.wordcounter: Count our precious

    11. pucelle.run-on-save: Automate PDF creation

    12. sandcastle.vscode-open: Opens docx files in Word

    13. thinker.sort-json: Format JSON by sorting on object keys

    14. tomoki1207.pdf: View PDF within VS Code

  4. Pandoc to generate docx documents from AsciiDoctor’s DocBook exports;

  5. MS Word for cleaning up manuscripts before they go to editors, publishers, or publishing tools;

  6. Optionally you can also:

    1. add a Github Account for cloud backups and ensure you have enough LFS storage;

Configuration

All configuration files are commented where not deemed self-explanatory. Skip or change values to meet your needs.

Keybindings

From Shift+Cmd+P, choose Preferences: Open Keyboard Shortcuts (JSON) and add the keybindings below:

[
  {
    // Run configuration snippet for .asciidoctoroconfig.adoc
    "args": {
      "name": "Configure asciidoctorconfig.adoc"
    },
    "command": "editor.action.insertSnippet",
    "key": "alt+a",
    "when": "editorTextFocus && editorLangId == asciidoc"
  },
  {
    // Save AsciiDoc as Docx
    // Saves to intermediate XML, which is hidden and deleted
    "command": "macros.convertAsciiDocToDocx",
    "key": "alt+d",
    "when": "editorFocus && editorLangId == asciidoc"
  },
  {
    // Run ToCome snippet
    "args": {
      "name": "Add to come"
    },
    "command": "editor.action.insertSnippet",
    "key": "alt+k",
    "when": "editorTextFocus && editorLangId == asciidoc"
  },
  {
    // Toggle showing history of modifications
    "command": "gitlens.toggleGraph",
    "key": "alt+m"
  },
  {
    // Quick access to AsciiDoc snippets
    // After the key press, type to filter
    "command": "macros.asciidocSnippets",
    "key": "alt+s",
    "when": "editorFocus && editorLangId == asciidoc"
  },
  {
    // Toggle editing
    "args": {
      "find": "^:(!)?editing:$",
      "isRegex": true,
      "preserveSelections": true,
      "replace": ":${1:?:!}editing:"
    },
    "command": "findInCurrentFile",
    "key": "alt+t",
    "when": "editorTextFocus && editorLangId == asciidoc"
  },
  {
    // Profiling words from current AsciiDoc file
    "command": "extension.calculateWordStats",
    "key": "alt+w",
    "when": "editorFocus && editorLangId == asciidoc"
  },
  {
    // Toggle check-box ToDos
    // Cursor must be positioned within the ToDo text
    "args": {
      "find": "((?:\\*|//)\\s+\\[)( )?(x)?(\\].*?)(?=\\n|$)",
      "isRegex": true,
      "preserveSelections": true,
      "replace": "$1${2:?x:}${3:? :}$4",
      "restrictFind": "matchAroundCursor"
    },
    "command": "findInCurrentFile",
    "key": "alt+x",
    "when": "editorTextFocus && editorLangId == asciidoc"
  },
  {
    // Turn Zen mode off
    "command": "macros.zenModeOff",
    "key": "alt+z",
    "when": "inZenMode"
  },
  {
    // Turn Zen mode on
    "command": "macros.zenModeOn",
    "key": "alt+z",
    "when": "!inZenMode"
  },
  {
    // Workaround for "Cannot load JSON schema..." issue
    "command": "settings.cycle.vscodeIssue177142",
    "key": "alt+/",
    "when": "editorFocus && editorLangId == jsonc"
  }
]

User Settings

If things do not work as expected, check for any user-level configurations that could influence those set at the Workspace. The configuration precedence is: Default  User  Workspace  User.Language  Workspace.Language.

From Shift+Cmd+P, choose Preferences: Open User Settings (JSON) and apply the content below:

{
  "editor.fontLigatures": false, // Simplicity
  "explorer.confirmDelete": false, // Trashcan is available
  "explorer.confirmDragAndDrop": false, // Undo is available
  "grunt.autoDetect": "off",
  "gulp.autoDetect": "off",
  "jake.autoDetect": "off",
  "npm.autoDetect": "off",
  "telemetry.telemetryLevel": "off", // Privacy
  "typescript.tsc.autoDetect": "off",
  "window.autoDetectColorScheme": true, // OS-feel
  "window.nativeTabs": true, // OS-feel
  "window.titleBarStyle": "native", // Simplicity
  "workbench.colorTheme": "Kimbie Dark", // Restful
  "workbench.editor.decorations.badges": true, // Clarity
  "workbench.enableExperiments": false, // Stability
  "workbench.iconTheme": "material-icon-theme", // Descriptive icons
  "◊": true
}

Word Macros

This macro is intended to run in newly opened Word documents generated from a Composition AsciiDoc.

Lozenge assumes that you keep the macro below aligned with any changes you apply to lozenge/title_page.adoc or lozenge/template.docx_.

Add the below macro to the normal.dotx of your Word installation and assign it a keyboard shortcut using the category Macros.

Sub insertRoundedWordCount()
'
' insertRoundedWordCount Macro
' Inserts word count, rounded to the nearest thousand.
'

    Set formulaRound = Selection.Fields.Add(Range:=Selection.Range, Type:=wdFieldEmpty, Text:="=ROUND( , -3) \# #,##0", PreserveFormatting:=False)

    ' 2 characters for "{ " of the field delimiters and 7 characters for "=ROUND("
    ' The space between "(" and "," is because the countWords field will eat the space
    Set countWords = Selection.Fields.Add(Range:=formulaRound.Code.Characters(2 + 7), Type:=wdFieldEmpty, Text:="NUMWORDS", PreserveFormatting:=False)

    formulaRound.Update

End Sub

Sub deletePreamble()
'
' deletePreamble Macro
' Delete Preamble inserted by AsciiDoc/DocBook/Pandoc conversion path.
'
    ' Delete Pandoc cover page
    Selection.HomeKey Unit:=wdStory
    Application.Browser.Next
    Selection.HomeKey Unit:=wdStory, Extend:=wdExtend
    Selection.TypeBackspace

    ' Change Empty Header to Body Text
    Selection.HomeKey Unit:=wdStory
    Selection.Style = ActiveDocument.Styles("Normal")

    ' Find and format the contact information
    Selection.HomeKey Unit:=wdStory
    Selection.Find.ClearFormatting
    With Selection.Find
        .Text = ChrW(9674) & "Contact" & ChrW(9674) & "*" & ChrW(9674) & _
            "Contact" & ChrW(9674)
        .Replacement.Text = ""
        .Forward = True
        .Wrap = wdFindContinue
        .Format = False
        .MatchCase = False
        .MatchWholeWord = False
        .MatchAllWordForms = False
        .MatchSoundsLike = False
        .MatchWildcards = True
    End With
    Selection.Find.Execute
    Selection.Style = ActiveDocument.Styles("ContactInfo")

    ' Find and remove contact information markers
    Selection.HomeKey Unit:=wdStory
    Selection.Find.ClearFormatting
    Selection.Find.Replacement.ClearFormatting
    With Selection.Find
        .Text = ChrW(9674) & "Contact" & ChrW(9674)
        .Replacement.Text = ""
        .Forward = True
        .Wrap = wdFindContinue
        .Format = False
        .MatchCase = False
        .MatchWholeWord = False
        .MatchWildcards = False
        .MatchSoundsLike = False
        .MatchAllWordForms = False
    End With
    Selection.Find.Execute Replace:=wdReplaceAll

    ' Update Header
    Selection.HomeKey Unit:=wdStory
    If ActiveWindow.View.SplitSpecial <> wdPaneNone Then
        ActiveWindow.Panes(2).Close
    End If
    If ActiveWindow.ActivePane.View.Type = wdNormalView Or ActiveWindow. _
        ActivePane.View.Type = wdOutlineView Then
        ActiveWindow.ActivePane.View.Type = wdPrintView
    End If
    ActiveWindow.ActivePane.View.SeekView = wdSeekCurrentPageHeader
    ActiveWindow.ActivePane.View.NextHeaderFooter
    Selection.WholeStory
    Selection.Fields.Update
    ActiveWindow.ActivePane.View.SeekView = wdSeekMainDocument

    ' Find a replace WordCount placeholder with actual word count
    Selection.HomeKey Unit:=wdStory
    With Selection.Find
        .MatchWildcards = False
        .Text = "◊WordCount◊"
        .Execute
    End With
    Application.Run MacroName:="insertRoundedWordCount"

    'Back to top of document
    Selection.HomeKey Unit:=wdStory

    ' Save clean-up work
    ActiveDocument.Save

End Sub

About

Twenty Thousand Leagues under the Sea by Jules Verne

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published