R-Markdown's render_site function is deleting the contents of the .git folder - r

Im trying to version control a website generated with R-Markdown's render_site function by pushing it directly from the output directory, the default _site folder. Problem is, every time i call the render_site function it clears most of the content of the .git folder (save for the objects folder within) and breaks the link between the local and remote directory. Is there any way to stop this from happening? Curiously, the clean_site function clears the exact same folders and files from the .git folder so im guessing the problem is related to some post build cleanup.
The webpage directory looks something like this:
_site/
├── /.git
├── /index_files
├── /about_files
├── intex.html
├── about.html
└── styles.css
The .git folder before rendering the site looks like:
.git/
├── /hooks
├── /info
├── /logs
├── /objects
├── /refs
├── COMMIT_EDITMSG
├── config
├── description
├── FETCH_HEAD
├── HEAD
└── index
And after building only the objects folder is left:
.git/
└── /objects
I should also note that rendering each .Rmd file into htmls individually does not cause the same problem.

The default clean function for the site generator doesn't exclude anything. You can replace it fairly easily, using a scheme something like this:
Choose a name for your new generator, and put it in the YAML for the index.Rmd file, e.g.
site: my_site
Write my_site to modify the default generator (or the original custom one,
if you already had one):
my_site <- function(...) {
site <- rmarkdown:::default_site(...) # or bookdown::bookdown_site(...), etc.
# Modify the clean function
oldclean <- site$clean
site$clean <- function(...) {
files <- oldclean(...)
# leave out any filename containing .git
grep("[.]git", files, value = TRUE, invert = TRUE)
}
site
}
I haven't tested this and might have the pattern wrong in the new clean function, but it should be close to working.
You might also want to suggest to the rmarkdown authors (on their Github site) that it would be nice to have a way to mark certain files to exclude from cleaning.

Related

Is there a general convention for naming files and folders?

I'm working on a program that generates simple text files to save the state of users.
To keep things organized, I have a folder for users. Nested inside, I create a folder for each user with their ID, like this:
[Program Name]\currentusers\36a7781b
Inside of these folders I save a text file with the state of the user. At the moment I'm calling the file simply "appstate."
I have three questions:
Is there a convention for naming folders? E.g. currentusers, currentUsers, CurrentUsers, current_users.
Is there a convention for naming files? E.g. appstate, appState, AppState, app_state.
These are text files —should they include the .txt extension, or are they fine without it?
In order:
1) Yes, there is a convention to name folders. End the foldername with .d like foldername.d. This is used a lot in /etc/, but isn't too common to use. I never use it, and I barely see it except in old "things"
2) File basenames (that's the name of the file without an extension or path) are usually minorcase, and are often separated with - or _. There are no rules. Just avoid spaces or weird symbols. Keep it alphanumerical, for your own and others' sake.
3) POSIX doesn't understand extensions, but also doesn't care if you add them. Users do, and makes it easier for users (and editors/viewers) to know how to handle files.
You said your files are text files (and if it's raw text, end them with .txt), but I believe what you mean is that the files are not binary files (aka readable by a human). I believe your files have some sort of data structure that is parsed by your program, forming some sort of database with folders and users... thus your files are data files (ending with .dat as a convention).
So... all in all:
MyProgram/
├── anna
│   ├── birthday.dat
│   └── name.dat
├── dog
│   ├── birthday.dat
│   └── name.dat
├── john-smith
│   ├── birthday.dat
│   └── name.dat
├── mike
│   ├── birthday.dat
│   └── name.dat
└── rachel
├── birthday.dat
└── name.dat
5 directories, 10 files

File download in Voila from Jupyter Notebook

There are many questions with great answers about downloading a file from a Jupyter Notebook. Here's one I added to earlier. That works, but I am unable to click and download that file for a server started with Voila.
Originally I realized I could not download the basic case when clicked through Voila.
from IPython.display import display, FileLink
local_file = FileLink('./demo.xlsx', result_html_prefix="Click here to download: ")
display(local_file)
That is from my notebook. I am able to click on the link and download the file. When I start my notebook with Voila it looks more like this..
Clicking the link give a 404 ☝️ for a voila server started with
voila mynotebook.ipynb
Since the file clearly isn't being served... I found this link here and tried:
voila mynotebook.ipynb --VoilaConfiguration.file_whitelist="['demo.xlsx']"
which unfortunately didn't work.
I saw static content can be served in voila.. I'll keep playing down this road. Has anyone done this before?
I was able to make it work by hosting my file to download as static content as I was trying before. All of this is for a Mac, but it'll be similar for other platforms.
I had to define a custom template in order to get files at static_root so they could be served. Relevant documentation is here for setting up a custom template.
It isn't difficult.. you essentially create a directory where it's expected, copy over some of the default files, then add/change what you will. terminal record might look something like this:
cd ~/Library/Jupyter/voila/templates/
mkdir foobar
export DEFAULT_TEMPLATE_PATH=~/anaconda3/envs/voilatest/share/jupyter/voila/templates/default
export TEMPLATE_PATH=~/Library/Jupyter/voila/templates/foobar
cp -r $DEFAULT_TEMPLATE_PATH/nbconvert_templates $TEMPLATE_PATH
cp -r $DEFAULT_TEMPLATE_PATH/templates $TEMPLATE_PATH
to which the tree will look like this in my new custom template:
{~/Library/Jupyter/voila/templates/foobar}$ tree .
.
├── nbconvert_templates
│   ├── base.tpl
│   ├── lab.tpl
│   └── voila.tpl
├── static
│   └── demo.xlsx
└── templates
├── 404.html
├── browser-open.html
├── error.html
├── page.html
└── tree.html
3 directories, 9 files
notice the static directory with demo.xlsx. I added that in. That is the file I wanted to download via the link.
Starting voila like this...
voila mynotebook.ipynb --template=foobar
Now.. in mynotebook.ipynb
Use an HTML Anchor tag to do the download. At least FileLink fails for me with the following error.
Path (/voila/static/demo.xlsx) doesn't exist. It may still be in the process of being generated, or you may have the incorrect path.
which isn't much of a surprise since the actual path the file is stored at isn't that. It just happens to be the static content uri.
%%html
Download Excel Sheet
Using an anchor will make it hardcoded and I didn't have any issues. I'll also be able to style the anchor more anyways. One catch.. This doesn't work in a regular notebook anymore since it's a URI to a served resource under voila.

How to tar all files in current directory using tar but without inputing names of tar file and all files?

ENV:
macOS Sierra 10.12.6
Raw input(example):
.
├── f1.md
├── f2.md
├── f3.md
├── f4.txt
├── f5.csv
└── f6.doc
0 directories, 6 files
In a test folder, there are 6 files.
Expected output:
.
├── all.tar
├── f1.md
├── f2.md
├── f3.md
├── f4.txt
├── f5.csv
└── f6.doc
0 directories, 7 files
Trying and Problem
tar -cvf all.tar f1.md f2.md f3.md f4.txt f5.csv f6.doc
Though I get the result from the above method but I have to inputing all file names and the compressed file name, which is inconvenient. For example , I can select all files and right click, then choose compressed option without inputing all.tar (I don't mind the .tar filenames.)
Hope
command-line method without inputing specific file names.
In case you want all files, including those in the subdirectories (or if you have no subdirectories), you would run:
tar -cvf all.tar *
Then, bash would expand * into the list of all files in the current directory, including subdirectories.
In case you want only those files in the current directory, but NOT in the subdirectories, then you would have to use find, in a more complicated command. Let me know if this is the case for you, and I can take the time to find that combination of commands for you.

Is there any UNIX way to create a figure of a directory structure?

I want to generate a simple figure (something like this) with sub directory names, file names in a directory. Is there any easiest way in *nix to do this?
I often need to submit all my analysis results to core biologists, I feel that it would be easy for them to navigate to the files & figures they need, if I provide this kind of figure also.
Thank you very much.
You could use the tree command.
It will display a tree like structure for a directory.
tree
.
└── foo
├── bar
│   └── test
├── bar2
│   └── test
└── test

Sinatra asset pipeline, can't make it work

I am using Sprockets with Sinatra, as suggested in Sinatra's page docs, but I can't make it work.
When I go to localhost:4567, the page loads correctly but with no styles. If I go to localhost:4567/assets/app.css, I get a not found error. I wonder what I am missing or what is wrong in the way I am using Sprockets?
This is my folder structure:
├── assets
│   ├── css
│   │   ├── app.css
│   │   ├── base.css
│   │   └── normalize.css
├── bin
│   └── app
├── lib
│   ├── app_assets.rb
│   └── main.rb
├── spec
│   ├── spec_helper.rb
│   └── main_spec.rb
├── views
│   └── index.erb
├── Gemfile
├── Gemfile.lock
├── Rakefile
├── .rspec
└── .ruby-version
The contents of app.css are:
//= require normalize
//= require base
The contents of app_assets.rb are:
module AppAssets
def self.environment root_path
environment = Sprockets::Environment.new root_path
environment.append_path './assets/css/'
environment
# get assets
get '/assets/*' do
env['PATH_INFO'].sub!('/assets', '')
settings.environment.call(env)
end
end
end
The contents of lib/main.rb are:
require 'sinatra'
require 'sprockets'
require 'app_assets'
class Main < Sinatra::Base
set :views, "#{settings.root}/../views"
get '/' do
erb :index
end
end
The file views/index.erb contains the line:
<link rel="stylesheet" href="assets/app.css">
And the contents of bin/app are:
#!/usr/bin/env ruby
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
require 'sinatra'
require 'sprockets'
require 'app_assets'
require 'main'
Main.run!
Which I run typing:
$ bin/app
Any help would be appreciated, I'm sure I made something wrong but I can't see what. Can anybody spot it?
The app_assets.rb file is the problem here. When you require this file inside another file, the methods you define inside this module are not automatically included. You need to explicitly include AppAssets wherever you need the self.environment method to exist.
The second issue here is that self.environment is not equivalent to settings.environment. If I understand correctly, what you're trying to do is define the asset routing whenever the module gets included. To achieve this one way is to use the included hook for modules. This hook gets run every time you include a module inside a context. If you use that, the code in app_assets.rb turns to:
module AppAssets
def self.included(klass)
environment = Sprockets::Environment.new klass.settings.root
# note the change to path. Since the file where this gets included
# is inside a sub-folder, we need to traverse to one level above.
environment.append_path '../assets/css/'
klass.set :environment, environment
klass.get '/assets/*' do
env['PATH_INFO'].sub!('/assets', '')
klass.settings.environment.call(env)
end
end
end
The klass argument to this hook is the class into which this module is included. In our case this is the Sinatra class you've described in main.rb. That file looks like:
class Main < Sinatra::Base
include AppAssets
# Same as what you have
end
There's a Sinatra Recipes article about using Sprockets with Sinatra: http://recipes.sinatrarb.com/p/asset_management/sprockets?#article

Resources