What's the recommended way to copy multiple dotfiles with yeoman? - yeoman

I am building a yeoman generator for a fairly typical node app:
/
|--package.json
|--.gitignore
|--.travis.yml
|--README.md
|--app/
|--index.js
|--models
|--views
|--controllers
In the templates folder of my yeoman generator, I have to rename the dotfiles (and the package.json) to prevent them from being processed as part of the generator:
templates/
|--_package.json
|--_gitignore
|--_travis.yml
|--README.md
|--app/
|--index.js
|--models
|--views
|--controllers
I see a lot of generators that copy dotfiles individually manually:
this.copy('_package.json', 'package.json')
this.copy('_gitignore', '.gitignore')
this.copy('_gitattributes', '.gitattributes')
I think it's a pain to manually change my generator code when I add new template files. I would like to automatically copy all files in the /templates folder, and rename the ones that are prefixed with _.
What's the best way to do this?
If I were to describe my intention in imaginary regex, this is what it would look like:
this.copy(/^_(.*)/, '.$1')
ths.copy(/^[^_]/)
EDIT
This is the best I can manage:
this.expandFiles('**', { cwd: this.sourceRoot() }).map(function() {
this.copy file, file.replace(/^_/, '.')
}, this);

I found this question through Google as I was looking for the solution, and then I figured it out myself.
Using the new fs API, you can use globs!
// Copy all non-dotfiles
this.fs.copy(
this.templatePath('static/**/*'),
this.destinationRoot()
);
// Copy all dotfiles
this.fs.copy(
this.templatePath('static/.*'),
this.destinationRoot()
);

Adding to #callumacrae 's answer: you can also define dot: true in the globOptions of copy(). That way a /** glob will include dotfiles. Example:
this.fs.copy(
this.templatePath('files/**'),
this.destinationPath('client'),
{ globOptions: { dot: true } }
);
A list of available Glob options can be found in the README of node-glob.

Just got this working for me: the globOptions needs to be in the fifth argument:
this.fs.copyTpl(
this.templatePath('sometemplate/**/*'),
this.destinationPath(this.destinationRoot()),
null,
null,
{ globOptions: { dot: true } }
);

If you don't want to use templates that starts with a dot, you can use the dive module to achieve something identical:
var templatePath = this.templatePath('static-dotfiles');
var destinationRoot = this.destinationRoot();
dive(templatePath, {all: true}, function (err, file, stat) {
if (err) throw err;
this.fs.copy(
file,
(destinationRoot + path.sep + path.relative(templatePath, file))
.replace(path.sep + '_', path.sep + '.')
);
}.bind(this));
where static-dotfiles is the name of your template folder for dotfiles where _ replaces . in filenames (ex: _gitignore).
Don't forget to add a requirement to dive at the top of your generator with
var dive = require('dive');
Of course, this also works for copyTpl.
Note that all subparts of paths that starts with a _ will be replaced by a . (ex: static-dotfiles/_config/_gitignore will be generated as .config/.gitignore)

Related

Require json file dynamically in react-native (from thousands of files)

I googled so far and tried to find out the solution but not yet.
I know require() works only with static path, so I want alternative ways to solve my problem. I found this answer here but it doesnt make sense for thousands of resources.
Please advise me the best approach to handle such case.
Background
I have thousand of json files that containing app data, and declared all the file path dynamically like below:
export var SRC_PATH = {
bible_version_inv: {
"kjv-ot": "data/bibles/Bible_KJV_OT_%s.txt",
"kjv-nt": "data/bibles/Bible_KJV_NT_%s.txt",
"lct-ot": "data/bibles/Bible_LCT_OT_%s.txt",
"lct-nt": "data/bibles/Bible_LCT_NT_%s.txt",
"leb": "data/bibles/leb_%s.txt",
"net": "data/bibles/net_%s.txt",
"bhs": "data/bibles/bhs_%s.txt",
"n1904": "data/bibles/na_%s.txt",
.....
"esv": "data/bibles/esv_%s.txt",
.....
},
....
As you can see, file path contains '%s' and that should be replace with right string depends on what the user selected.
For example if user select the bible (abbreviation: "kjv-ot") and the chapter 1 then the file named "data/bibles/Bible_KJV_OT_01.txt" should be imported.
I'm not good enough in react-native, just wondering if there is other alternative way to handle those thousands of resource files and require only one at a time by dynamically following the user's selection.
Any suggestions please.
Instead of exporting a flat file, you could export a function that took a parameter which would help build out the paths like this:
// fileInclude.js
export const generateSourcePath = (sub) => {
return {
bible_version_inv: {
"kjv-ot": `data/bibles/Bible_KJV_OT_${sub}.txt`
}
}
}
//usingFile.js
const generation = require('./fileInclude.js');
const myFile = generation.generateSourcePath('mySub');
const requiredFile = require(myFile);
then you would import (or require) this item into your project, execute generateSourcePath('mysub') to get all your paths.

Can't get Dart asset_pack package example code to run correctly

So I am trying to make a game in Dart and I decided to check out this asset_pack package. I tried to test the example code (below) but asset.imported prints null..why is this?
I did create /web/test/foo.txt in my project folder and put a little bit of text in it but still I get null printed.
main() {
// Construct a new AssetManager.
AssetManager assets = new AssetManager();
// Register the 'test' pack. No url is needed so the empty string suffices.
AssetPack testPack = assets.registerPack('test', '');
// Register asset 'foo' and load it's contents from 'foo.txt'.
// The asset type is 'text' and there are no arguments for the loader
// or importer.
Future<Asset> futureAsset = testPack.loadAndRegisterAsset('foo', 'foo.txt',
'text', {}, {})
futureAsset.then((asset) {
// Print the contents of foo.txt.
print(asset.imported);
});
}
I think your file has to be in the web/ folder or you have to load test/foo.txt. If you run the example you should see an error that the file was not found in the developer console. This code seems to work:
Future<Asset> futureAsset = testPack.loadAndRegisterAsset('foo', 'text',
'test/foo.txt', {}, {})

Batch mkdir using Yeoman

I am creating a Yeoman generator app. I want to create a set of parent directories and each parent directory has the same set of child templates.
Right now I am using the below commands repeatedly to achieve this. Is there a better way to loop over an array and achieve the same?
this.mkdir('app/scss/modules/tables');
this.mkdir('app/scss/modules/navigation');
this.mkdir('app/scss/modules/pagination');
this.copy('_extends.scss', 'app/scss/modules/navigation/_extends.scss');
this.copy('_mixins.scss', 'app/scss/modules/navigation/_mixins.scss');
this.copy('_variables.scss', 'app/scss/modules/navigation/_variables.scss');
this.copy('_extends.scss', 'app/scss/modules/pagination/_extends.scss');
this.copy('_mixins.scss', 'app/scss/modules/pagination/_mixins.scss');
this.copy('_variables.scss', 'app/scss/modules/pagination/_variables.scss');
this.copy('_extends.scss', 'app/scss/modules/tables/_extends.scss');
this.copy('_mixins.scss', 'app/scss/modules/tables/_mixins.scss');
this.copy('_variables.scss', 'app/scss/modules/tables/_variables.scss');
I reckon you'd need two arrays, and at least two loops.
In pseudocode:
dirs = [ ... directories ... ];
files = [ ... files ... ];
for (directory in dirs) {
mkdir (d);
for (file in files) {
copy(file, directory + file);
}
}
If you ever need another directory with all files, or another file to go in all directories you'd just add it to the corresponding array.
Hope you find this useful!
You could also do something like this:
dirs = [ "folder1", "folder2", "etc" ];
files = [ "file1", "file2", "etc" ];
dirs.forEach(function(directory){
this.mkdir(directory);
files.forEach(function(file){
this.copy(file, directory + file);
}.bind(this));
}.bind(this));
...if you want to avoid using a 'for-in' loop, since they're somewhat error-prone.

Upload file Yii The second argument to copy() function cannot be a directory

I'm trying to upload file but get this error message :
move_uploaded_file() [<a href='function.move-uploaded-file'>function.move-uploaded-file</a>]: The second argument to copy() function cannot be a directory
I think there's something problem with this file but I've no idea to solve it..
<?php
class FileUploadController extends CController {
public function actionUpload() {
$model = new FileUpload();
$form = new CForm('application.views.fileUpload.uploadForm', $model);
if ($form->submitted('submit') && $form->validate()) {
$form->model->image = CUploadedFile::getInstance($form->model, 'image');
if($model->validate())
{
$model->image->saveAs('/opt/lampp/htdocs/upl/images');
Yii::app()->user->setFlash('success', 'File Uploaded');
$this->redirect(array('upload'));
}
}
$this->render('upload', array('form' => $form));
}
}
?>
You either need to check all files existed at '/opt/lampp/htdocs/upl/images' and check if the same named file is available or not, if available then just rename the file with extra "_1" every time, or you can always upload the file by renaming the file into some machine name sort of thing see the code below,
$name = rand(1000,9999) . time(); // rand(1000,9999) optional
$name = md5($name); //optional
$model->image->saveAs('/opt/lampp/htdocs/upl/images/' . $name . '.jpg');
This is what I usually do with file uploads, provided that you're saving the files references into the database or in any text file.
EDIT
Get Extension.
In case if you're required to get extension of the file rather then of hard-coded, you can use $model->image->getExtensionName(); it will get you the extension of the uploaded file without . (dot)
Finally, I solved it by myself:
The problem was located in line
$model->image->saveAs('/opt/lampp/htdocs/upl/images');
It should be :
$model->image->saveAs('/opt/lampp/htdocs/upl/images/images.jpg');
Now, there's another problem: when I upload 'new image', it will be replace the old file, I want the file(s) being uploaded not replaced the old file or I need something like rename as new file. Does anyone knows?
goto cuploadedfile.php .
over write this function with this
if($this->_error==UPLOAD_ERR_OK)
{
if($deleteTempFile)
return move_uploaded_file($this->_tempName,$file."/".$this->getName());
elseif(is_uploaded_file($this->_tempName))
return copy($this->_tempName, $file."/".$this->getName());
else
return false;
}
thank u.........

"Temp" directory in Windows, IO.getFile

I would like to write to the C:\windows\temp directory (or it's configured equivalent) inside my Firefox-addon.
https://developer.mozilla.org/en/FileGuide/FileWriting
Gives the impression that there are system independent names for these paths:
var file = IO.getFile("Desktop", "myinfo.txt");
var stream = IO.newOutputStream(file, "text");
stream.writeString("This is some text");
stream.close();
But I can't find any reference in the specified references, as to what "Desktop" points to. So that leaves me not knowing what exactly is referred to in the names given by the documentation.
How to I use IO.getFile() to open a file in the windows global temp folder?
See also Code snippets: File I/O on developer.mozilla.org. It answers your question (Matthew is right, it's "TmpD"), and provides many other file-related examples.
[edit] Oh, and does IO actually work for you? I thought it was unavailable. [edit2] I added a warning at the top of the pages I could find, that mention it.
The keys are described here.
I believe you want TmpD, which is listed here
// Writing stackoverflow.txt to TEMP dir
const { OS } = Cu.import("resource://gre/modules/osfile.jsm", {})
const path = OS.Path.join(OS.Constants.Path.tmpDir, "stackoverflow.txt")
OS.File.writeAtomic(path, "Hello, StackOverflow!", {
encoding: "utf-8",
tmpPath: "stackoverflow.txt.tmp", // it's not necessary but I'd recommend to use it
}).then(() => console.log(path, "has been written"))
// C:\Users\traxium\AppData\Local\Temp\stackoverflow.txt has been written
// Reading stackoverflow.txt from TEMP dir
const { OS } = Cu.import("resource://gre/modules/osfile.jsm", {})
const path = OS.Path.join(OS.Constants.Path.tmpDir, "stackoverflow.txt")
OS.File.read(path, { encoding: "utf-8" }).then(txt => console.log(txt))
// "Hello, StackOverflow!"

Resources